-- ProcessLapJoint.lua by Egaltech s.r.l. 2021/06/21 -- Gestione calcolo mezzo-legno per Travi -- 2019/10/08 Agg. gestione OpenPocket. -- 2021/01/24 Con sega a catena ora sempre impostato asse A. -- 2021/02/03 Corretto riconoscimento feature di coda. -- 2021/02/04 Razionalizzata gestione forzatura lama. Corretta gestione diametro minimo utensile per svuotatura. -- 2021/03/04 Due facce con testa da sotto. -- 2021/03/20 Piccole correzioni. -- 2021/03/22 Modificata gestione caso due facce lunghe come la trave con trave corta. -- 2021/04/13 Modificata gestione fessura U con sega a catena (corta ora ok, lunga ancora da correggere). -- 2021/04/14 Correzioni ribasso a U con fresa da sotto. -- 2021/04/15 Aggiunta gestione massima lunghezza fresa da sotto su svuotature. -- 2021/04/21 Anche feature lunga con due facce con opzione lama ora si taglia con lama. -- 2021/04/23 Corretto caso con antischeggia non inseriti perchè inutili. -- 2021/04/27 Antischeggia solo se feature trasversali. -- 2021/05/12 Semplificata gestione diametro minimo utensile per svuotatura. -- 2021/06/04 Su U passante con faccia perpendicolare aggiunta si forza Pocket. -- 2021/06/11 Su U passante e profonda se non bastano due svuotature su faccia ortogonale si fa anche la faccia di fondo per quanto possibile. -- 2021/06/21 Nel caso precedente si fa la terza svuotatura anche se è possibile fare una sola delle prime due (altra da sotto). -- 2021/06/21 Gestione ripresa spigoli o contorno con fresa più piccola ( diametro < 3/4 utensile svuotatura) attivata da parametro Q. -- Tabella per definizione modulo local ProcessLapJoint = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Cut = require( 'ProcessCut') local DoubleCut = require( 'ProcessDoubleCut') local LongCut = require( 'ProcessLongCut') local Long2Cut = require( 'ProcessLongDoubleCut') local Fbs = require( 'FacesBySaw') EgtOutLog( ' ProcessLapJoint started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') -- variabili assegnazione parametri Q local Q_FORCE_BLADE = '' -- i local Q_DEPTH_CHAMFER = '' -- d local Q_ONLY_CHAMFER = '' -- i local Q_USE_MILL = '' -- i local Q_USE_ROUGH_TOOL = '' -- i local Q_USE_ROUGH_TOOL_B90 = '' -- i local Q_USE_ROUGH_TOOL_B0 = '' -- i local Q_BORE_ON_CORNER = '' -- 1 local Q_CONTOUR_SMALL_TOOL = '' -- i local Q_ONLY_CONTOUR = '' -- i local Q_SIDE_ROUGH_TOOL = '' -- i local Q_ANTISPLINT_TYPE = '' -- i -- variabile smussi local bMadeChamfer -- Settaggi interni local bTrySidePocketAtFirst = true --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessLapJoint.Identify( Proc) return ( (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 33) or (( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34) or ( Proc.Grp == 4 and Proc.Prc == 37) or ( Proc.Grp == 4 and Proc.Prc == 39) or ( Proc.Grp == 4 and Proc.Prc == 120)) end --------------------------------------------------------------------- local function AssignQIdent( Proc) -- reset assegnazione parametri Q Q_FORCE_BLADE = '' Q_DEPTH_CHAMFER = '' Q_ONLY_CHAMFER = '' Q_USE_MILL = '' Q_USE_ROUGH_TOOL = '' Q_USE_ROUGH_TOOL_B90 = '' Q_USE_ROUGH_TOOL_B0 = '' Q_BORE_ON_CORNER = '' Q_CONTOUR_SMALL_TOOL = '' Q_ONLY_CONTOUR = '' Q_SIDE_ROUGH_TOOL = '' Q_ANTISPLINT_TYPE = '' if ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16 then Q_FORCE_BLADE = 'Q01' -- i Q_DEPTH_CHAMFER = 'Q04' -- d Q_ONLY_CHAMFER = 'Q05' -- i elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17 then Q_DEPTH_CHAMFER = 'Q01' -- d Q_ONLY_CHAMFER = 'Q02' -- i elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20 then Q_DEPTH_CHAMFER = 'Q01' -- d Q_USE_MILL = 'Q02' -- i Q_USE_ROUGH_TOOL = 'Q03' -- i Q_USE_ROUGH_TOOL_B90 = 'Q04' -- i Q_USE_ROUGH_TOOL_B0 = 'Q05' -- i Q_BORE_ON_CORNER = 'Q06' -- i elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25 then Q_BORE_ON_CORNER = 'Q01' -- i elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30 then Q_CONTOUR_SMALL_TOOL = 'Q01' -- i Q_ONLY_CONTOUR = 'Q02' -- i Q_SIDE_ROUGH_TOOL = 'Q03' -- i Q_ANTISPLINT_TYPE = 'Q06' -- i Q_DEPTH_CHAMFER = 'Q07' -- d elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32 then Q_SIDE_ROUGH_TOOL = 'Q01' -- i Q_ANTISPLINT_TYPE = 'Q06' -- i elseif ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34 then Q_ANTISPLINT_TYPE = 'Q06' -- i end -- le altre features gestite non hanno parametri Q end --------------------------------------------------------------------- local function EvaluateQParam( Proc) -- verifico che lo smusso sia richiesto local nChamfer = 0 local dDepth = EgtGetInfo( Proc.Id, Q_DEPTH_CHAMFER, 'd') or 0 if dDepth > 0 then nChamfer = 1 end -- verifico se posso fare solo lo smusso if EgtGetInfo( Proc.Id, Q_ONLY_CHAMFER, 'i') == 1 then if dDepth > 0 then nChamfer = nChamfer + 1 -- altrimenti se non ho l'affondamento esco else local sErr = 'Error : no chamfer depth' EgtOutLog( sErr) return -1, dDepth, sErr end end -- verifico se devo usare lama invece della sega-catena -- 2020-03-20 forzata abilitazione uso lama se parametro Q non è presente -- xxxx-xx-xx tolta la preferenza alla lama in favore della sega-catena per un caso particolare -- 2021-02-15 re-introdotta la preferenza alla lama se non c'è il parametro Q. Rimane da -- implementare un ulteriore parametro per poter scegliere di prediligere la sega-catena o no al fine di continuare -- a cambiare il codice per gestire il caso particolare local bForceUseBlade = false if #Q_FORCE_BLADE == 0 or EgtGetInfo( Proc.Id, Q_FORCE_BLADE, 'i') == 1 then bForceUseBlade = true end return nChamfer, dDepth, sErr, bForceUseBlade end --------------------------------------------------------------------- local function TestElleShape3( Proc) -- valida solo nel caso di tre facce if Proc.Fct ~= 3 then return false end -- determino se L con una faccia terminale o U con tre facce local bIsL = true for i = 1, 3 do local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.Id, i - 1)[1] -- le conto local nCount = 0 for j = 1, #vFacAdj do if vFacAdj[j] >= 0 then nCount = nCount + 1 end end if nCount == 1 then bIsL = false break end end return bIsL end --------------------------------------------------------------------- local function TestElleShape4( Proc) -- valida solo nel caso di quattro facce if Proc.Fct ~= 4 then return false end -- determino se L con due facce terminali o O local nFac3Adj = 0 local dMinArea3 = GEO.INFINITO * GEO.INFINITO local dMaxArea2 = 0 for i = 1, 4 do local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.Id, i - 1)[1] -- le conto local nCount = 0 for j = 1, #vFacAdj do if vFacAdj[j] >= 0 then nCount = nCount + 1 end end local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, i - 1, GDB_ID.ROOT) local dArea = dH * dV if nCount == 2 then dMaxArea2 = max( dMaxArea2, dArea) elseif nCount == 3 then dMinArea3 = min( dMinArea3, dArea) nFac3Adj = nFac3Adj + 1 end end if nFac3Adj ~= 2 then return false end -- verifico se L profonda oppure lunga if dMinArea3 < 2 * dMaxArea2 then return 1 else return 2 end end --------------------------------------------------------------------- local function GetChainSawBlockedAxis( nInd) if BD.GetChainSawBlockedAxis then return BD.GetChainSawBlockedAxis( nInd) else if nInd == 1 then return EgtIf( BD.C_SIMM, 'A=90', 'A=0') else return EgtIf( BD.C_SIMM, 'A=0', 'A=90') end end end --------------------------------------------------------------------- local function VerifyChainSaw( Proc, dMinDim, dMaxDim, vtOrtho) local bUseChainSaw = false local sMchFind = 'Sawing' local sSawing = ML.FindSawing(sMchFind) local dMaxMat = 0 local dSawCornerRad = 0 local dSawThick = 0 local dMaxDepth = 200 -- se non trova una lavorazione di sawing esco if not sSawing then return bUseChainSaw else -- recupero i dati dell'utensile local dToolLength = 0 local dSawWidth = 75 if EgtMdbSetCurrMachining( sSawing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat dSawWidth = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawWidth dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick dSawCornerRad = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) or dSawCornerRad dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end if dSawThick < dMinDim + 10 * GEO.EPS_SMALL and dSawWidth < dMaxDim + 10 * GEO.EPS_SMALL then bUseChainSaw = true end end end return bUseChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick, dMaxDepth end --------------------------------------------------------------------- local function VerifyIfPocket( Proc, dDiam, vtOrtho, dDepth, sMchFindMaster) -- tipo di svuotatura local sMchFind = EgtIf( sMchFindMaster and #sMchFindMaster > 0, sMchFindMaster, 'Pocket') -- ricerca della svuotatura local sPocketing if dDepth then sPocketing = ML.FindPocketing( sMchFind, dDiam, dDepth) or ML.FindPocketing( sMchFind, dDiam, 2/3 * dDepth) or ML.FindPocketing( sMchFind, dDiam) else sPocketing = ML.FindPocketing( sMchFind, dDiam) end if not sPocketing then return false end -- recupero i dati dell'utensile local bUsePocketing = false local dMaxDepth = 0 local dToolDiam = 0 if EgtMdbSetCurrMachining( sPocketing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end bUsePocketing = true end return bUsePocketing, sPocketing, dMaxDepth, dToolDiam end --------------------------------------------------------------------- local function VerifyIfByBHSideMill( Proc) local bUseBHSideMill = false local bHead = true local bHeadDir = true local sMilling local dMaxMat = 10 local dToolDiam = 0 -- se non feature BlockHausHalfLap o non abilitato parametro Q per lavorarlo di fianco esco local nUseSideTool = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0 if Proc.Prc ~= 37 and nUseSideTool == 0 then return false end -- verifico se U local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc)) -- se U e lunghezza non richiede spezzatura if bIsU and Proc.Box:getDimX() <= BD.LONGCUT_MAXLEN then -- recupero la lavorazione sMilling = ML.FindMilling( 'BHSideMill') if sMilling then -- recupero i dati dell'utensile local dToolLength = 0 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat end end -- verifico se la feature è abbastanza vicino a testa/coda da permettere la lavorazione con questo utensile -- recupero l'ingombro della trave local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL) local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if b3Solid then local dMinXF = Proc.Box:getMin():getX() local dMaxXF = Proc.Box:getMax():getX() local dMinT = b3Solid:getMin():getX() local dMaxT = b3Solid:getMax():getX() -- determino se è più vicino alla testa o al bordo (con offset per evitare problemi a metà) bHeadDir = ( dMaxT - dMinXF) < ( dMaxXF - dMinT) + 50 bHead = bHeadDir -- determino se è compatibile con il massimo affondamento dell'utensile bUseBHSideMill = EgtIf( bHead, ( dMaxT - dMinXF), ( dMaxXF - dMinT)) < dMaxDepth -- se diametro maggiore della testa if BD.HEAD_DIM_FOR_BH and dToolDiam > BD.HEAD_DIM_FOR_BH then bHead = true bUseBHSideMill = true end end end end return bUseBHSideMill, bHead, bHeadDir, sMilling, dMaxMat, dToolDiam end --------------------------------------------------------------------- local function GetTunnelDimension( Proc, nPartId) -- ottengo i versori delle 4 facce e ottengo l'orientamento del tunnel -- recupero il numero di facce local nFacCnt = EgtSurfTmFacetCount( Proc.Id) -- recupero l'ingombro della trave local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- variabili dimensioni fessura e id faccia lunga local dDimMin local dDimMax local nLongIdFace = 0 local bOppoFace = false -- ottengo il versore ortogonale local ptN1, vtN1 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) local vtOrtho = vtN1 ^ vtN2 if vtOrtho:isSmall() then _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, 2, GDB_ID.ROOT) vtOrtho = vtN1 ^ vtN2 bOppoFace = true end -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta la profondità della fessura local frFc = Frame3d( ptN1, vtOrtho) ; local bBoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc) local dDepth = bBoxLoc:getDimZ() -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end -- mi assicuro che la Z del punto utilizzato per creare la superficie sia alla Z media del bounding box locale local ptN2 = Point3d(ptN1) ptN2:toLoc(frFc) ptN2 = Point3d( ptN2:getX(), ptN2:getY(), ( bBoxLoc:getMin():getZ() + bBoxLoc:getMax():getZ())/2) ptN2:toGlob(frFc) -- creo superficie intermedia local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptN2, vtOrtho, b3Solid, GDB_ID.ROOT) -- ritaglio la superficie con le facce della fessura for i = 1, nFacCnt do local ptN, vtN = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT) EgtCutSurfTmPlane( nSurfInt, ptN, -vtN, false, GDB_ID.ROOT) end local _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT) dDimMin = min( DimH, DimV) dDimMax = max( DimH, DimV) _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacCnt-1, GDB_ID.ROOT) -- se faccia pari alla larghezza fessura if abs(DimH - dDimMax) < GEO.EPS_SMALL or abs(DimV - dDimMax) < GEO.EPS_SMALL then nLongIdFace = nFacCnt-1 -- altrimenti verifico anche con la faccia precedente else local nFaceToCheck = EgtIf( bOppoFace, nFacCnt-3, nFacCnt-2) -- prendo le dimensioni della faccia e poi confronto con il minimo _, DimH, DimV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFaceToCheck, GDB_ID.ROOT) -- se trovato con il minimo, questa seconda faccia non è la più lunga if abs(DimH - dDimMin) < GEO.EPS_SMALL or abs(DimV - dDimMin) < GEO.EPS_SMALL then nLongIdFace = nFacCnt-1 else nLongIdFace = nFaceToCheck end end if not dDimMax then return dDimMin, dDimMax, dDepth, nil, nil end return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt end --------------------------------------------------------------------- local function GetFaceAdj( Proc, nFacInd, dH, dV) -- Recupero le facce adiacenti alla principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' return -1, sErr end EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 4) -- Riordino le dimensioni per avere dH > dV if dH < dV then dH, dV = dV, dH end -- Cerco una faccia adiacente alla principale sul lato lungo local nFacAdj for i = 1, #vAdj do if vAdj[i] >= 0 then local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) local dLen = dist( ptP1, ptP2) if dLen > 0.5 * dH then nFacAdj = vAdj[i] EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 4) break end end end if not nFacAdj then local sErr = 'Error : main face without long adjacent face' return -1, sErr end return nFacAdj end --------------------------------------------------------------------- local function CalcCollisionSafety( vtDir) local dCollSic = 8 * BD.COLL_SIC if abs( vtDir:getX()) > 0.996 or abs( vtDir:getY()) > 0.996 or abs( vtDir:getZ()) > 0.996 then dCollSic = 0 elseif abs( vtDir:getX()) > 0.866 or abs( vtDir:getY()) > 0.866 or abs( vtDir:getZ()) > 0.866 then dCollSic = 2 * BD.COLL_SIC elseif abs( vtDir:getX()) > 0.707 or abs( vtDir:getY()) > 0.707 or abs( vtDir:getZ()) > 0.707 then dCollSic = 5 * BD.COLL_SIC end return dCollSic end --------------------------------------------------------------------- -- Verifica se feature di testa function ProcessLapJoint.IsHeadFeature( Proc, b3Raw, dCurrOvmH) -- se una sola faccia if Proc.Fct == 1 then local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) if vtN0:getX() > 0.1 then return true end end -- verifico se è in testa if Proc.Box:getMax():getX() < b3Raw:getMax():getX() - dCurrOvmH - BD.MAX_DIST_HTFEA then return false end -- la sua lunghezza non deve superare il massimo e 60% della lunghezza della trave if Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.6 *b3Raw:getDimX()) then return false end -- recupero identificativo del pezzo local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL) -- se una o due facce e interessa veramente la testa, allora di testa if Proc.Fct <= 2 then local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if Proc.Box:getMax():getX() > b3Solid:getMax():getX() - 1. then return true elseif Proc.Box:getMax():getX() < b3Solid:getMax():getX() - 5. then return false end end -- deve avere la normale principale diretta verso la testa local nFacInd, dElev = BL.GetFaceWithMostAdj( Proc.Id, nPartId) local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) if vtN and vtN:getX() < 0.499 then return false elseif Proc.Fct >= 5 then return true end -- deve occupare la maggior parte dell'area if Proc.Box:getDimY() > 0.75 * b3Raw:getDimY() or Proc.Box:getDimZ() > 0.75 * b3Raw:getDimZ() then return true end -- non è di testa return false end --------------------------------------------------------------------- -- Verifica se feature di coda function ProcessLapJoint.IsTailFeature( Proc, b3Raw) -- se una sola faccia if Proc.Fct == 1 then local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) if vtN0:getX() < -0.1 then return true end end -- in base al tipo di feature attribuisco il significato dei parametri Q AssignQIdent( Proc) -- se può essere fatto con utensile tipo lama local bUseBHSideMill, bHead, bHeadDir = VerifyIfByBHSideMill( Proc) if bUseBHSideMill then Proc.HeadDir = bHeadDir return not bHead end -- verifico se è in coda local dEndDist = Proc.Box:getMin():getX() - b3Raw:getMin():getX() if dEndDist > BD.MAX_DIST_HTFEA then return false end -- la sua lunghezza non deve superare il massimo e 60% della lunghezza della trave if Proc.Box:getDimX() > min( BD.MAX_LEN_HTFEA, 0.6 * b3Raw:getDimX()) then return false end -- recupero identificativo del pezzo local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL) -- se una o due facce e interessa veramente la coda, allora di coda if Proc.Fct <= 2 then local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if Proc.Box:getMin():getX() < b3Solid:getMin():getX() + 1. then return true elseif Proc.Box:getMin():getX() > b3Solid:getMin():getX() + 5. then return false end end -- deve avere la normale principale diretta verso la coda (oppure tunnel) local nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( Proc.Id, nPartId) local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) if vtN and vtN:getZ() < BD.NZ_MINA and nFacInd2 then ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) nFacInd, nFacInd2 = nFacInd2, nFacInd dElev, dElev2 = dElev2, dElev end if not vtN or vtN:getX() > -0.001 or dEndDist + vtN:getX() * dElev > 0 then return false else return true end end --------------------------------------------------------------------- -- Classificazione della feature function ProcessLapJoint.Classify( Proc, b3Raw) -- se 1 faccia if Proc.Fct == 1 then -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- verifico se è lavorabile solo dal basso --local bDown = ( vtN:getZ() < BD.NZ_MINA) --return true, bDown return true, false -- se 2 facce elseif Proc.Fct == 2 then -- dati delle facce local ptC = {} local vtN = {} ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) -- verifico se è lavorabile solo dal basso local bSmall = ( ( Proc.Head or Proc.Tail) and Proc.Box:getDimX() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ())) or ( not ( Proc.Head or Proc.Tail) and Proc.Box:getDimY() <= BD.GetMaxLenRidgeLapFromBottom( b3Raw:getDimZ())) local bDown = ( vtN[1]:getZ() < BD.NZ_MINB and vtN[2]:getZ() < BD.NZ_MINB) or ( vtN[1]:getZ() < BD.NZ_MINA and ( vtN[2]:getZ() < -0.1 or not bSmall)) or ( vtN[2]:getZ() < BD.NZ_MINA and ( vtN[1]:getZ() < -0.1 or not bSmall)) bDown = ( bDown and not BD.DOWN_HEAD) return true, bDown -- se più di 2 facce else local bClosedOrthoFaces local nDeletedFace -- recupero la faccia con il maggior numero di adiacenze e minor elevazione local nPartId = EgtGetParent( EgtGetParent( Proc.Id) or GDB_ID.NULL) local nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( Proc.Id, nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 else return false end end -- se è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then return false end -- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura for i = 1, Proc.Fct do local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL -- elimino una faccia nDeletedFace = i - 1 if EgtSurfTmRemoveFacet( nNewProc, nDeletedFace) then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa nFacInd, dElev, nFacInd2, dElev2 = BL.GetFaceWithMostAdj( nNewProc, nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 EgtErase( nNewProc) break else EgtErase( nNewProc) return false end end -- altrimenti esco else EgtErase( nNewProc) break end end -- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo if bClosedOrthoFaces then nFacInd = nDeletedFace -- rendo nulla la faccia opzionale perchè si tratta di una fessura nFacInd2 = nil dElev = BL.GetFaceElevation( Proc.Id, nFacInd) bClosedOrthoFaces = false -- non lo setto come tunnel end end -- se facce formano un tunnel e sono ortogonali if bClosedOrthoFaces then -- ottengo le dimensioni del tunnel local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = GetTunnelDimension( Proc, nPartId) EgtErase(nSurfInt) -- verifico se può essere fatto con svuotatura if VerifyIfPocket( Proc, dDimMin, vtOrtho) then return true, false elseif VerifyChainSaw( Proc, dDimMin, dDimMax, vtOrtho) then return true, false else return false end else local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- se può essere fatto con utensile tipo lama local bUseBHSideMill, _, _, _, dMaxMat = VerifyIfByBHSideMill( Proc) if bUseBHSideMill and ( dMaxMat <= dV + 15 * GEO.EPS_SMALL) then return true, false -- altrimenti controllo se deve essere ruotato con le altre lavorazioni else -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) -- cerco se c'è faccia adiacente sul lato più lungo local nFaceAdj = GetFaceAdj( Proc, nFacInd, dH, dV) or -1 local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2) -- verifico se è lavorabile solo dal basso local bDown = ( vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD) -- se verso il basso, verifico se utilizzabile seconda faccia if bDown then if nFacInd2 and dElev2 < 2 * dElev then local ptC2, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) bDown = ( vtN2:getZ() < BD.NZ_MINB) elseif not nFacInd2 and bIsL and nFaceAdj >= 0 then local ptC2, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFaceAdj, GDB_ID.ROOT) bDown = ( vtN2:getZ() < BD.NZ_MINB) end -- verifico se la faccia principale è sottosquadra, ha forma L ed esiste la faccia adiacente elseif vtN:getZ() < -0.2589 and bIsL and nFaceAdj >= 0 then -- box del pezzo local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- se il numero di facce > 2 o il box della feature supera una certa distanza dalle teste allora controllo la z della faccia ausiiaria if Proc.Fct > 2 or ( Proc.Box:getMax():getX() < b3Solid:getMin():getX() - 150) or ( Proc.Box:getMin():getX() > b3Solid:getMax():getX() + 150) then local ptC2, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFaceAdj, GDB_ID.ROOT) bDown = ( vtN2:getZ() < BD.NZ_MINB) end end return true, bDown end end end end --------------------------------------------------------------------- -- Lavorazione con fresa --------------------------------------------------------------------- local function MakeOneFaceByMill( Proc, nPhase, nRawId, nPartId) -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) -- recupero l'ingombro della trave local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- verifico il numero di facce della tacca assert( ( Proc.Fct == 1), 'Error : MakeOneFaceByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces') -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) -- verifico se orientata verso l'alto local bUp = ( vtN:getZ() >= BD.NZ_MINA) -- scelta faccia da lavorare local nFacInd = 0 -- recupero la lavorazione local sMilling = ML.FindMilling( 'BirdsMouth') if not sMilling then local sErr = 'Error : BirdsMouth not found in library' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione di fresatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto uso faccia e lato correzione if vtN:getX() > 0 then EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_LEFT, MCH_MILL_FU.PARAL_LEFT)) else EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bUp, MCH_MILL_FU.ORTHO_RIGHT, MCH_MILL_FU.PARAL_RIGHT)) end -- imposto lato di correzione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) if not bUp then EgtSetMachiningParam( MCH_MP.INVERT, true) end -- imposto posizione braccio porta testa if vtN:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- dichiaro non si generano sfridi per VMill EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- eventuale segnalazione ingombro di testa o coda local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * b3Raw:getDimZ()) if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + dMinHIng then if Proc.Head then local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX() BL.UpdateHCING( nRawId, dOffs) elseif Proc.Tail then local dOffs = Proc.Box:getMax():getX() - b3Solid:getMin():getX() BL.UpdateTCING( nRawId, dOffs) end end return true end --------------------------------------------------------------------- local function MakeTwoFacesByMill( Proc, nPhase, nRawId, nPartId, bDownHead) -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) -- recupero l'ingombro della trave local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- verifico il numero di facce della tacca assert( ( Proc.Fct == 2), 'Error : MakeTwoFacesByMill in LapJoint with ' .. tostring( Proc.Fct) .. ' faces') -- recupero il parametro Q per uso fresa local nUseRM = EgtGetInfo( Proc.Id, Q_USE_MILL, 'i') -- recupero la lavorazione local sMilling if nUseRM and nUseRM == 1 then sMilling = ML.FindMilling( 'LongSmallCut' .. EgtIf( bDownHead, '_H2', '')) else sMilling = ML.FindMilling( 'BirdsMouth' .. EgtIf( bDownHead, '_H2', '')) end if not sMilling then local sErr = 'Error : LongSmallCut & BirdsMouth not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dTDiam = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam end -- dati delle facce local ptC = {} local vtN = {} ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) -- dati medi local ptM = ( ptC[1] + ptC[2]) / 2 -- verifico non siano orientate verso il basso local bFaceOk = {} bFaceOk[1] = ( vtN[1]:getZ() >= BD.NZ_MINB) bFaceOk[2] = ( vtN[2]:getZ() >= BD.NZ_MINB) if not bDownHead and not bFaceOk[1] and not bFaceOk[2] then local sErr = 'Error : LapJoint from bottom impossible' EgtOutLog( sErr) return false, sErr end -- scelta faccia da lavorare local nFacInd -- se entrambe possibili if bFaceOk[1] and bFaceOk[2] then -- se in testa, scelgo quella orientata verso la testa if Proc.Head then if vtN[1]:getX() > vtN[2]:getX() then nFacInd = 0 else nFacInd = 1 end -- se altrimenti in coda, scelgo quella orientata verso la coda elseif Proc.Tail then if vtN[1]:getX() < vtN[2]:getX() then nFacInd = 0 else nFacInd = 1 end -- altrimenti, scelgo quella con la normale più perpendicolare all'asse trave (se uguali, quella verso X+) else if abs( abs( vtN[1]:getX()) - abs( vtN[2]:getX())) < GEO.EPS_SMALL then if ptM:getX() > b3Raw:getCenter():getX() then nFacInd = EgtIf( vtN[1]:getX() > vtN[2]:getX(), 0, 1) else nFacInd = EgtIf( vtN[1]:getX() < vtN[2]:getX(), 0, 1) end else nFacInd = EgtIf( abs( vtN[1]:getX()) < abs( vtN[2]:getX()), 0, 1) end end elseif bFaceOk[1] then nFacInd = 0 else nFacInd = 1 end local nOthInd = 1 - nFacInd local sName local nMchFId local nFaceUse -- se forzato uso fresa controllo se posso fare in una o più passate if nUseRM and nUseRM == 1 then -- prendo la larghezza della faccia local _, pPt1, pPt2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nOthInd, GDB_ID.ROOT) local dDistPoint = dist( pPt1, pPt2) local _, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) local dWidth = EgtIf( abs( dDistPoint - dH) < abs( dDistPoint - dV), dV, dH) -- se larghezza faccia maggiore diametro utensile aggiungo una lavorazione if dTDiam > 0 and dWidth > dTDiam then -- inserisco la lavorazione di fresatura sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_1' nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto uso faccia e lato correzione nFaceUse = BL.GetNearestOrthoOpposite( vtN[nOthInd+1]) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto lato di correzione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- tolgo l'inversione EgtSetMachiningParam( MCH_MP.INVERT, false) -- aggiungo offset laterale EgtSetMachiningParam( MCH_MP.OFFSR , (dTDiam/2)) -- imposto posizione braccio porta testa if vtN[nFacInd+1]:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- dichiaro non si generano sfridi per VMill EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end -- inserisco la lavorazione di fresatura sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto uso faccia e lato correzione nFaceUse = BL.GetNearestOrthoOpposite( vtN[nOthInd+1]) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto lato di correzione EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- tolgo l'inversione EgtSetMachiningParam( MCH_MP.INVERT, false) -- imposto posizione braccio porta testa if vtN[nFacInd+1]:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- dichiaro non si generano sfridi per VMill EgtSetMachiningParam( MCH_MP.USERNOTES, 'VMRS=0;') -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- eventuale segnalazione ingombro di testa o coda local dMinHIng = min( 0.5 * BD.VICE_MINH, 0.5 * b3Raw:getDimZ()) if Proc.Box:getDimZ() > dMinHIng and Proc.Box:getMin():getZ() < b3Raw:getMin():getZ() + dMinHIng then if Proc.Head then local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX() BL.UpdateHCING( nRawId, dOffs) elseif Proc.Tail then local dOffs = Proc.Box:getMax():getX() - b3Solid:getMin():getX() BL.UpdateTCING( nRawId, dOffs) elseif Proc.Box:getCenter():getX() > b3Solid:getCenter():getX() then local dOffs = b3Solid:getMax():getX() - Proc.Box:getMin():getX() local dDist = b3Solid:getMax():getX() - Proc.Box:getMax():getX() -- sempre concavo aumento la distanza (rimane una punta...) dDist = dDist + 10 BL.UpdateHCING( nRawId, dOffs, dDist) end end return true end --------------------------------------------------------------------- local function MakePreCuts( Proc, nPhase, nRawId, nPartId, dOvmHead, b3Raw, nChamfer) -- se interessa l'intera sezione della trave, necessaria sgrossatura if nChamfer < 2 and Proc.Box:getDimY() > 0.9 * b3Raw:getDimY() and Proc.Box:getDimZ() > 0.9 * b3Raw:getDimZ() then -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end -- aggiungo sgrossatura e la lavoro local AddId = EgtSurfTmConvexHullInBBox( nAddGrpId, Proc.Id, b3Raw, GDB_RT.GLOB) if AddId then EgtSetName( AddId, 'AddCut_' .. tostring( Proc.Id)) -- applico lavorazione local CutProc = { Id = AddId, Grp = Proc.Grp, Prc = Proc.Prc, Box = Proc.Box, Fct = Proc.Fct, Flg = Proc.Flg, Head = Proc.Head, Tail = Proc.Tail, CutId = Proc.CutId, TaskId = Proc.TaskId} local nCutFacet = EgtSurfTmFacetCount( AddId) if nCutFacet == 1 then return Cut.Make( CutProc, nPhase, nRawId, nPartId, dOvmHead) elseif nCutFacet == 2 then return DoubleCut.Make( CutProc, nPhase, nRawId, nPartId, dOvmHead) end end end return true end --------------------------------------------------------------------- local function MakeByMill( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dElev, dCollSic, bSpecialApp, sMillMaster, nFacInd2, dFacElev2) -- Cerco una faccia adiacente alla principale sul lato lungo local nFacAdj, sErr = GetFaceAdj( Proc, nFacInd, dH, dV) if nFacAdj < 0 then EgtOutLog( sErr) return false, sErr end -- Determino se estremi aperti o chiusi e faccia adiacente da aggiungere alla lavorazione local bOpenStart = false local bOpenEnd = false local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1] EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3) local _, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacAdj, GDB_ID.ROOT) -- Riordino le dimensioni per avere dH > dV if dH2 < dV2 then dH2, dV2 = dV2, dH2 end local nFacAdj2 for j = 1, #vAdj2 do if vAdj2[j] == nFacInd then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == nFacInd do i = EgtIf( i > 1, i - 1, #vAdj2) end bOpenStart = ( vAdj2[i] < 0) -- Se non esiste faccia adiacente a lato successivo -> fine aperto local k = EgtIf( j < #vAdj2, j + 1, 1) while vAdj2[k] == nFacInd do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) end -- decommentare questa parte per concatenare due facce --if bSpecialApp and vAdj2[j] >= 0 then -- local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacAdj, vAdj2[j], GDB_ID.ROOT) -- local dLen = dist( ptP1, ptP2) -- if abs( dLen - dV2) < 10 * GEO.EPS_SMALL then -- nFacAdj2 = vAdj2[j] -- end --end end -- Recupero la lavorazione di fresa local sMilling if bSpecialApp then sMilling = sMillMaster else sMilling = ML.FindMilling( 'LongSmallCut') if not sMilling then sErr = 'Error : LongSmallCut not found in library' EgtOutLog( sErr) return false, sErr end end -- recupero i dati dell'utensile local dTDiam = 50 local dMaxMat = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat end end -- Se massimo materiale utensile è molto inferiore dell'elevazione non faccio la lavorazione e do un warning if dMaxMat > 0 and dMaxMat + 15 < dElev + dCollSic then sWarn = 'Warning : skipped milling; elevation bigger than max tool depth' return true, sWarn, dMaxMat end -- Calcolo uso faccia local nFaceUse = BL.GetNearestParalOpposite( rfFac:getVersZ()) -- inserisco la lavorazione di fresatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria if nFacAdj2 then EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj},{ Proc.Id, nFacAdj2}}) else EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}}) end -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_YM if rfFac:getVersZ():getY() > 100 * GEO.EPS_ZERO then nSCC = MCH_SCC.ADIR_YP end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto accorciamento iniziale/finale per estremi aperti/chiusi if bSpecialApp then -- applico gli allungamenti o accorciamenti considerando che la lavorazione è invertita if nFacAdj2 then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, dTDiam / 2, - dTDiam / 2)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, dTDiam / 2, - dTDiam / 2)) -- confronto la faccia applicata nella lavorazione(faccia adiacente) con la seconda faccia passata nella funzione -- se corrispondono allora aggiungo una estensione nei lati chiusi pari all'elevazione della stessa faccia corrispondente if nFacAdj == nFacInd2 then if not bOpenStart then EgtSetMachiningParam( MCH_MP.LOPERP, dFacElev2) end if not bOpenEnd then EgtSetMachiningParam( MCH_MP.LIPERP, dFacElev2) end end end -- applico elevazione local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenEnd, 0, - dTDiam / 2)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenStart, 0, - dTDiam / 2)) end -- eseguo if not EgtApplyMachining( true, false) then _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end return true, '', dTDiam end --------------------------------------------------------------------- local function ChooseCorner( Proc, nFacInd) -- Recupero le adiacenze della faccia principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] -- Cerco i corner tra le facce adiacenti alla principale local tFacAdj = {} for i = 1, #vAdj do if vAdj[i] >= 0 then for j = i+1, #vAdj do if vAdj[j] >= 0 then local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, vAdj[i], vAdj[j], GDB_ID.ROOT) if ptP1 and ptP2 and dAng < 0 then local dLen = dist( ptP1, ptP2) table.insert( tFacAdj, { vAdj[i], vAdj[j], dLen, ptP1, ptP2, dAng}) end end end end end -- Tra le linee dei corner determino la più lunga local dMaxLen = 0 local nIdLine for i = 1, #tFacAdj do if tFacAdj[i][3] > dMaxLen then nIdLine = i dMaxLen = tFacAdj[i][3] end end return dMaxLen, nIdLine, tFacAdj end --------------------------------------------------------------------- local function ChooseBlindContour( Proc, nFacInd) -- Recupero le adiacenze della faccia principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] -- Cerco le facce adiacenti con angolo convesso local tFacAdjMain = {} for i = 1, #vAdj do if vAdj[i] >= 0 then local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) if ptP1 and ptP2 and dAng < 0 then local dLen = dist( ptP1, ptP2) table.insert( tFacAdjMain, { vAdj[i], dLen, ptP1, ptP2, dAng}) end end end return tFacAdjMain end --------------------------------------------------------------------- local function CheckToInvert( AuxId, bPositive) -- recupero versore estrusione local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT) -- faccio una copia del percorso local sParnt = EgtGetParent( AuxId) local nNewEntId = EgtCopyGlob( AuxId, sParnt) -- chiudo il percorso if EgtCloseCurveCompo( nNewEntId) then local vtMPlane, dDist, dArea = EgtCurveArea( nNewEntId) -- cancello percorso copia EgtErase( nNewEntId) if dArea and abs(dArea) > 1 then local frEnt = EgtGetGlobFrame( AuxId) if vtMPlane then vtMPlane:toGlob(frEnt) if dArea and dArea * ( vtMPlane * vtExtr) < 0 then if bPositive then return true end elseif dArea and dArea * ( vtMPlane * vtExtr) > 0 then if not bPositive then return true end end end end else -- cancello percorso copia EgtErase(nNewEntId) end return false end --------------------------------------------------------------------- local function SetOpenSide( nPathInt, vtOrtho, b3Solid, nAddGrpId, nStartPoint) -- fondo tra loro le curve compatibili EgtMergeCurvesInCurveCompo( nPathInt) local nStartIdEnt, nNumEnt = EgtCurveDomain( nPathInt) local pLastPIni, pLastPEnd -- faccio una copia della curva e la esplodo if nStartIdEnt then -- prendo i punti for i = 1, nNumEnt do local pPini = EgtUP( nPathInt, (i-1), GDB_RT.GLOB) local pPend = EgtUP( nPathInt, EgtIf( i == nNumEnt, 0, i), GDB_RT.GLOB) -- Se normale lungo la Z considero il box in X e Y if abs(vtOrtho:getZ()) > 0.999 then -- se corrisponde a X if ( abs( pPini:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend -- altrimenti se corrisponde a Y elseif ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend end -- altrimenti se normale lungo la Y considero il box in X e Z elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getY()) > 0.999 then -- se corrisponde a X if ( abs( pPini:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL and abs( pPend:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend -- altrimenti se corrisponde a Z elseif ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend end -- caso che non dovrebbe mai capitare ma gestito per completezza -- altrimenti se normale lungo la X considero il box in Y e Z elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getX()) > 0.999 then -- se corrisponde a Y if ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend -- altrimenti se corrisponde a Z elseif ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend end -- se asse Z orizzontale verifico se si avvicina piú a Y elseif abs(vtOrtho:getZ()) < 0.001 then if abs(vtOrtho:getY()) > 0.75 then -- se corrisponde a Z if ( abs( pPini:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMax():getZ()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL and abs( pPend:getZ() - b3Solid:getMin():getZ()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend end end -- se asse Y a 0 (fresa ne davanti ne dietro) verifico se si avvicina piú a Z+ elseif abs(vtOrtho:getY()) < 0.001 then if abs(vtOrtho:getZ()) > 0.75 then -- se corrisponde a Y if ( abs( pPini:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMax():getY()) < 10 * GEO.EPS_SMALL) or ( abs( pPini:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL and abs( pPend:getY() - b3Solid:getMin():getY()) < 10 * GEO.EPS_SMALL) then -- setto l'entità open local sActInfo = EgtGetInfo( nPathInt, 'OPEN', 's') or '' if #sActInfo > 0 then EgtSetInfo( nPathInt, 'OPEN', sActInfo .. ',' .. (i-1)) else EgtSetInfo( nPathInt, 'OPEN', (i-1)) end -- prendo i punti per eventuale modifica del punto di inizio percorso pLastPIni = pPini pLastPEnd = pPend end end end end -- se devo cambiare il punto di partenza if nStartPoint then if pLastPIni and pLastPEnd then -- calcolo il punto medio con gli ultimi punti utilizzati local ptPs = ( pLastPIni + pLastPEnd) / 2 EgtChangeClosedCurveStartPoint( nPathInt, ptPs, GDB_RT.GLOB) -- se devo eliminare la parte open if nStartPoint == 2 then EgtRemoveCurveCompoCurve( nPathInt, true) EgtRemoveCurveCompoCurve( nPathInt, false) end end end end end --------------------------------------------------------------------- local function MakeRoundCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam) -- recupero la lavorazione senza considerare l'elevazione local sMilling = ML.FindMilling( 'LongSmallCut') if not sMilling then local sMyWarn = 'Warning : clean corner milling/tool not found in library' EgtOutLog( sMyWarn) return true, sMyWarn end -- recupero i dati dell'utensile local dTDiam = 50 local dTMaxDepth = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam dTMaxDepth = EgtTdbGetCurrToolMaxDepth() or dTMaxDepth end -- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco if dTDiam > ( 0.75 * dDiam) then local sMyWarn = 'Warning : tool diameter not enough small' EgtOutLog( sMyWarn) return true, sMyWarn end -- ottengo gli angoli dove applicare il percorso con fresa più piccola local dMaxLen, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd) -- se non trovato nessun angolo interno valido esco if #tFacAdj == 0 then return true end -- recupero la normale della faccia di fondo local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) -- se fresatura da sotto salto la lavorazione if vtN1:getZ() < BD.DRILL_VZ_MIN then local sErr = 'Error : milling from bottom ' EgtOutLog( sErr) return false, sErr end -- ciclo su tutti gli angoli trovati local sMyWarn = '' for i = 1, #tFacAdj do local pAuxId = {} -- le 2 facce di contatto devono essere perpendicolari e non sottosquadra rispetto alla faccia di fondo local _, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][1], GDB_ID.ROOT) local _, ptP1x, ptP2x, dAngx = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[i][2], GDB_ID.ROOT) if dAng >= 0 or dAng < -90 - 10 * GEO.EPS_SMALL or dAngx >= 0 or dAngx < -90 - 10 * GEO.EPS_SMALL then goto continue end -- prendo la lunghezza di adiacenza delle due linee local dLen1 = dist( ptP1, ptP2) local dLen2 = dist( ptP1x, ptP2x) -- cerco il punto tra le 3 facce: nIdEndPoint local nIdIniPoint local nIdEndPoint if ptP1 and ptP2 then if dist( ptP1, tFacAdj[i][4]) < GEO.EPS_SMALL or dist( ptP2, tFacAdj[i][4]) < GEO.EPS_SMALL then nIdEndPoint = 4 nIdIniPoint = 5 elseif dist( ptP1, tFacAdj[i][5]) < GEO.EPS_SMALL or dist( ptP2, tFacAdj[i][5]) < GEO.EPS_SMALL then nIdEndPoint = 5 nIdIniPoint = 4 end end -- devo avere un punto comune if not nIdEndPoint then goto continue end -- calcolo lunghezza minima in base all'angolo tra le due pareti local dMinDist = (( dDiam / 2) / tan( ( 180 + tFacAdj[i][6]) / 2)) + 2 -- verifico che entrambe le linee siano maggiori delle lunghezza minima if dLen1 <= dMinDist or dLen2 <= dMinDist then sMyWarn = 'Warning : impossible make clean corner path' goto continue end -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro local ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1) < 10 * GEO.EPS_SMALL, ptP2, ptP1) -- prima linea local nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[i][nIdEndPoint], GDB_RT.GLOB) -- calcolo arretramento local dTrimDist = dLen1 - dMinDist -- se arretramento valido if dTrimDist > 100 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint , GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- se il punto finale corrisponde con il punto comune, uso l'altro ptApPoint = EgtIf( dist( tFacAdj[i][nIdEndPoint], ptP1x) < 10 * GEO.EPS_SMALL, ptP2x, ptP1x) -- seconda linea nAuxId = EgtLine( nAddGrpId, tFacAdj[i][nIdEndPoint], ptApPoint, GDB_RT.GLOB) -- calcolo arretramento dTrimDist = dLen2 - dMinDist -- se arretramento valido if dTrimDist > 100 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dTrimDist, ptApPoint , GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- trasformo in percorso local AuxId if #pAuxId > 0 then AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true) end -- deve esserci il percorso if not AuxId then sMyWarn = 'Warning : impossible make clean corner path' goto continue end -- modifico versore direzione EgtModifyCurveExtrusion( AuxId, vtN1, GDB_RT.GLOB) -- inserisco la lavorazione local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling goto continue end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- tipo attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) -- annullo allungamenti iniziale e finale EgtSetMachiningParam( MCH_MP.STARTADDLEN, 0) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 0) -- setto massimo affondamento possibile local dDepth = 0 if tFacAdj[i][3] > dTMaxDepth then dDepth = dTMaxDepth - tFacAdj[i][3] end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- setto se devo invertire il percorso local bInvert = CheckToInvert( AuxId, true) EgtSetMachiningParam( MCH_MP.INVERT, bInvert) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;' sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( ( tFacAdj[i][3] + dDepth), 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if EgtApplyMachining( true, false) then _, sMyWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) end -- altrimenti lavorazione non applicata else _, sMyWarn = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) end ::continue:: end if #sMyWarn > 0 then EgtOutLog( sMyWarn) end return true, sMyWarn end --------------------------------------------------------------------- local function MakeRoundCleanContour( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam, nFunction, bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid, dDepth, bOneShot) -- recupero la lavorazione senza considerare l'elevazione perché viene calcolata l'elevazione utile local sMilling = ML.FindMilling( 'LongSmallCut') if not sMilling then local sMyWarn = 'Warning : clean corner milling/tool not found in library' EgtOutLog( sMyWarn) return true, sMyWarn end -- recupero i dati dell'utensile local dTDiam = 50 local dTMaxDepth = 0 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam dTMaxDepth = EgtTdbGetCurrToolMaxDepth() or dTMaxDepth end -- se il diametro trovato non è minore dei 3/4 del diametro utilizzato in precedenza, esco if dTDiam > ( 0.75 * dDiam) then local sMyWarn = 'Warning : tool diameter not enough small' EgtOutLog( sMyWarn) return true, sMyWarn end local vtN1 local nFirstId, nNumId local dMaxElev local dExtraDepth = 0 local dCollSic = 0 -- se non ho la faccia aggiunta if not nPathInt then -- cerco gli angoli dove applicare il percorso con fresa piú piccola e i lati in comune local tFacAdjMain = ChooseBlindContour( Proc, nFacInd) -- se non trovato nessun angolo interno da pulire esco if #tFacAdjMain == 0 then return true end -- normale alla faccia di fondo vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) -- se fresatura da sotto salto la lavorazione if vtN1:getZ() < BD.DRILL_VZ_MIN then local sErr = 'Error : milling from bottom' EgtOutLog( sErr) return false, sErr end -- distanza di sicurezza per evitare collisioni dCollSic = CalcCollisionSafety( vtN1) -- elevazione massima della faccia dMaxElev = BL.GetFaceElevation( Proc.Id, nFacInd, nPartId) -- ciclo tutta la tabella local tPaths = {} local ptIniPath local ptMidDist local dMaxLen = 0 for i = 1, #tFacAdjMain do -- le 2 facce di contatto devono essere perpendicolari o non sottosquadra rispetto alla faccia di fondo local ptP1, ptP2, dAng ptP1 = tFacAdjMain[i][3] ptP2 = tFacAdjMain[i][4] dAng = tFacAdjMain[i][5] if ( dAng < 0 and dAng >= -90 - 10 * GEO.EPS_SMALL) then -- creo la linea da P1 a P2 local nAuxId = EgtLine( nAddGrpId, ptP1, ptP2, GDB_RT.GLOB) table.insert( tPaths, nAuxId) -- prendo la lunghezza massima e il punto medio if tFacAdjMain[i][2] > dMaxLen then ptIniPath = ptP1 dMaxLen = tFacAdjMain[i][2] ptMidDist = ( ptP1 + ptP2) / 2 end end end -- costruisco il/i percorso/i nFirstId, nNumId = EgtCurveCompoByReorder( nAddGrpId, tPaths, ptIniPath, true, GDB_RT.GLOB) if nFirstId then -- se un solo percorso e chiuso cambio il punto di inizio nell'entitá piú lunga if nNumId == 1 and EgtCurveIsClosed( nFirstId) then EgtChangeClosedCurveStartPoint( nFirstId, ptMidDist, GDB_RT.GLOB) end -- modifico versore direzione for i = 1, nNumId do EgtModifyCurveExtrusion( nFirstId + i - 1, vtN1, GDB_RT.GLOB) end end -- alrimenti ho la faccia aggiunta else -- assegno il percorso nFirstId = EgtCopyGlob( nPathInt, nAddGrpId) nNumId = 1 -- distanza di sicurezza per evitare collisioni dCollSic = CalcCollisionSafety( vtOrtho) -- calcolo elevazione dalla faccia trasversale aggiunta local dSurfIntElev = BL.GetOtherFaceElevation( Proc.Id, nSurfInt, 0) if bDoubleSide then dMaxElev = dSurfIntElev else dMaxElev = dDepth -- se la precedente svuotatura è stata fatta completamente in una sola volta if bOneShot then -- se non è possibile contornare completamente da una sola parte if dTMaxDepth <= ( dMaxElev + BD.CUT_EXTRA + dCollSic) then bDoubleSide = true dMaxElev = dSurfIntElev else dExtraDepth = dMaxElev - dSurfIntElev end -- altrimenti non è stata fatta completamente calcolo la distanza tra faccia aggiunta e profondità superficie else dExtraDepth = dMaxElev - dSurfIntElev end end -- normale alla faccia aggiunta vtN1 = Vector3d( vtOrtho) -- imposto i lati aperti SetOpenSide( nFirstId, vtOrtho, b3Solid, nAddGrpId, 2) end -- se non trovato il percorso, esco if not nFirstId then local sMyWarn = 'Warning : impossible make clean corner path' EgtOutLog( sMyWarn) return true, sMyWarn end -- assegno lavorazioni ad ogni percorso local sMyWarn = '' for i = 1, nNumId do local nIdPath = nFirstId + i - 1 local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling goto continue end -- aggiungo geometria EgtSetMachiningGeometry( {{ nIdPath, -1}}) -- inversione direzione utensile local bInvertMach = false if nPathInt then -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) if vtN1:getZ() < BD.NZ_MINA and abs(vtN1:getZ()) >= 0.707 then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true -- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti elseif not bDoubleSide and vtN1:getY() > GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true end end -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- tipo attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) -- allungo inizio e fine di 3/4 del diametro utensile EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam * 0.75) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam * 0.75) -- setto massimo affondamento possibile local dMachDepth = 0 if ( dMaxElev + BD.CUT_EXTRA + dCollSic) > dTMaxDepth then dMachDepth = dTMaxDepth - ( dMaxElev + BD.CUT_EXTRA) end EgtSetMachiningParam( MCH_MP.DEPTH, (dMachDepth+dExtraDepth)) -- setto se devo invertire il percorso local bInvert = CheckToInvert( nIdPath, true) EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bInvertMach, not bInvert, bInvert)) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;' sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( ( dMaxElev + dMachDepth), 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if EgtApplyMachining( true, false) then _, sMyWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) end -- altrimenti lavorazione non applicata else _, sMyWarn = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) end -- se devo applicare la contornatura anche sul lato opposto if bDoubleSide then sName = 'CleanOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) nMchId = EgtAddMachining( sName, sMilling) if not nMchId then sMyWarn = 'Warning : impossible add machining ' .. sName .. '-' .. sMilling goto continue end -- aggiungo geometria EgtSetMachiningGeometry( {{ nIdPath, -1}}) -- imposto direzione utensile opposta EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- tipo attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) -- allungo inizio e fine di 3/4 del diametro utensile EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam * 0.75) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam * 0.75) -- setto massimo affondamento possibile local dMachDepth = 0 if ( dMaxElev + BD.CUT_EXTRA + dCollSic) > dTMaxDepth then dMachDepth = dTMaxDepth - ( dMaxElev + BD.CUT_EXTRA) end EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- setto se devo invertire il percorso local bInvert = CheckToInvert( nIdPath, true) EgtSetMachiningParam( MCH_MP.INVERT, not bInvert) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;' sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( ( dMaxElev + dMachDepth), 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if EgtApplyMachining( true, false) then _, sMyWarn = EgtGetMachMgrWarning( 0) if EgtIsMachiningEmpty() then EgtSetOperationMode( nMchId, false) end -- altrimenti lavorazione non applicata else _, sMyWarn = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) end end ::continue:: end if #sMyWarn > 0 then EgtOutLog( sMyWarn) end return true, sMyWarn end --------------------------------------------------------------------- local function MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam, nFunction, bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid, dDepth, bOneShot) -- se modalitá pulitura spigoli e lavorazione di lato forzo a fare il contorno if nFunction == 2 and nPathInt then nFunction = 1 end -- se richiesta pulitura del contorno if nFunction == 1 then return MakeRoundCleanContour( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam, nFunction, bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid, dDepth, bOneShot) -- se richiesta pulitura dei soli corner elseif nFunction == 2 then return MakeRoundCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam) -- altri casi non previsti else return true end end --------------------------------------------------------------------- local function MakeSharpCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam) local sMyWarn = '' local pAuxId = {} local nAuxId local AuxId local ptApPoint local dLenTrimExt local sMilling local dMaxDepth = 0 -- cerco l'angolo di riferimento dove applicare il percorso di pulitura, altrimenti esco local dMaxLen, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd) if #tFacAdj == 0 then return true end -- prendo il primo versore local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT) local vtN3 = EgtSurfTmFacetNormVersor( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT) -- trovo il punto sulla superfice di riferimento local _, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT) local nIdIniPoint local nIdEndPoint if ptLocP1 and ptLocP2 then if dist( ptLocP1, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL or dist( ptLocP2, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL then nIdEndPoint = 4 nIdIniPoint = 5 elseif dist( ptLocP1, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL or dist( ptLocP2, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL then nIdEndPoint = 5 nIdIniPoint = 4 end end -- versore direzione local vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint] vtExtr:normalize() -- inserisco le prime tre linee if nIdIniPoint and nIdEndPoint then -- se fresatura da sotto salto la lavorazione if vtExtr:getZ() < BD.DRILL_VZ_MIN then local sErr = 'Error : clean corner milling from bottom impossible' EgtOutLog( sErr) return false, sErr end -- sommo i tre versori per avre una direzione media vtExtr = vtN1 + vtN2 + vtN3 vtExtr:normalize() -- recupero la lavorazione non calcolando l'elevazione sMilling = ML.FindMilling( 'CleanCorner', ( 0.5 * dDiam)) if not sMilling then local sErr = 'Error : CleanCorner not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile ( temporaneo, per compensare errore nella lavorazione) if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) dMaxDepth = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxDepth end -- l'altezza di taglio del tagliente corrisponde al raggio del raccordo che si riesce a coprire -- quindi confronto l'elevazione con il raggio utensile utilizzato per la svuotatura if dMaxDepth < ( dDiam * 0.5) - 100 * GEO.EPS_SMALL then sMyWarn = 'Warning : skip clean corner (the cut heigth is smaller to machine the corner radius)' EgtOutLog( sMyWarn) return false, sMyWarn end nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdIniPoint], tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then ptApPoint = ptLocP2 else ptApPoint = ptLocP1 end nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB) dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - (( dDiam/2) + 2) -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta if dLenTrimExt > 10 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint , GDB_RT.GLOB) -- prendo il nuovo punto finale ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- creo linea di ritorno nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB) table.insert( pAuxId, nAuxId) end -- inserisco le ultime tre linee + uscita discostata rispetto all'ingresso -- trovo il secondo punto sulla superfice di riferimento _, ptLocP1, ptLocP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][2], GDB_ID.ROOT) if ptLocP1 and ptLocP2 then -- se il punto finale corrisponde con il punto utilizzato in precedenza, uso l'altro if dist( tFacAdj[nIdLine][nIdEndPoint], ptLocP1) < 10 * GEO.EPS_SMALL then ptApPoint = ptLocP2 else ptApPoint = ptLocP1 end nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], ptApPoint, GDB_RT.GLOB) dLenTrimExt = dist( tFacAdj[nIdLine][nIdEndPoint], ptApPoint) - (( dDiam/2) + 2) -- se la distanza dei due punti della linea è maggiore dal raggio fresa + delta, trimmo al raggio fresa + delta if dLenTrimExt > 10 * GEO.EPS_SMALL then EgtTrimExtendCurveByLen( nAuxId , -dLenTrimExt, ptApPoint , GDB_RT.GLOB) -- prendo il nuovo punto finale ptApPoint = EgtEP( nAuxId, GDB_RT.GLOB) end table.insert( pAuxId, nAuxId) -- creo linea di ritorno nAuxId = EgtLine( nAddGrpId, ptApPoint, tFacAdj[nIdLine][nIdEndPoint], GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- piccolo scostamento di 2mm dall'angolo nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint], tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), GDB_RT.GLOB) table.insert( pAuxId, nAuxId) -- ultima linea di risalita nAuxId = EgtLine( nAddGrpId, tFacAdj[nIdLine][nIdEndPoint] + ( 2 * vtExtr), tFacAdj[nIdLine][nIdIniPoint] + ( 2 * vtExtr), GDB_RT.GLOB) table.insert( pAuxId, nAuxId) end -- trasformo in percorso if #pAuxId > 0 then AuxId = EgtCurveCompo( nAddGrpId, pAuxId, true) end -- se non c'é il percorso do errore if not AuxId then local sErr = 'Error : impossible make clean corner path' EgtOutLog( sErr) return false, sErr end -- modifico versore direzione EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB) -- inserisco la lavorazione local sName = 'Clean_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameVectorApprox( vtN1, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN1:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN1:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- tipo attacco e uscita EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.NONE) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.AS_LI) -- allungo inizio e fine di 10mm EgtSetMachiningParam( MCH_MP.STARTADDLEN, 10) EgtSetMachiningParam( MCH_MP.ENDADDLEN, 10) -- setto affondamento 0 EgtSetMachiningParam( MCH_MP.DEPTH, 0) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill e massima elevazione local sUserNotes = 'VMRS=0;MaxElev=' .. EgtNumToString( dMaxDepth, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not 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 else return true, ( sMyWarn or sWarn) end end return true, sMyWarn end --------------------------------------------------------------------- local function MakeDrillOnCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiam, bSpecialMach) local sMyWarn = '' -- ottengo l'angolo dove applicare il foro local dMaxLen, nIdLine, tFacAdj = ChooseCorner( Proc, nFacInd) -- se non trovato nessun angolo interno valido esco if #tFacAdj == 0 then return true, sMyWarn end -- trovo il punto sulla superfice di riferimento local _, ptLocP1, ptLocP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, tFacAdj[nIdLine][1], GDB_ID.ROOT) local nIdIniPoint local nIdEndPoint if ptLocP1 and ptLocP2 then if ( dist( ptLocP1, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[nIdLine][4]) < GEO.EPS_SMALL) then nIdEndPoint = 4 nIdIniPoint = 5 elseif ( dist( ptLocP1, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL) or ( dist( ptLocP2, tFacAdj[nIdLine][5]) < GEO.EPS_SMALL) then nIdEndPoint = 5 nIdIniPoint = 4 end end -- inserisco foro if nIdIniPoint and nIdEndPoint then local vtExtr if bSpecialMach then local _, vtN0 = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) local _, vtN1 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][1], GDB_ID.ROOT) local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, tFacAdj[nIdLine][2], GDB_ID.ROOT) vtExtr = vtN0 + vtN1 + vtN2 else -- versore direzione vtExtr = tFacAdj[nIdLine][nIdIniPoint] - tFacAdj[nIdLine][nIdEndPoint] end vtExtr:normalize() -- se foratura da sotto salto la lavorazione if vtExtr:getZ() < BD.DRILL_VZ_MIN then local sErr = 'Error : drilling from bottom impossible' EgtOutLog( sErr) return false, sErr end -- recupero la lavorazione local sDrilling, nType = ML.FindDrilling( dDiam) if not sDrilling then local sErr = 'Error : drilling not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dMaxDepth = 20 local dDiamTool = 20 local dDiamTh = 35 local bIsDrilling if EgtMdbSetCurrMachining( sDrilling) then bIsDrilling = ( EgtMdbGetCurrMachiningParam( MCH_MP.TYPE) == MCH_MY.DRILLING) local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then if bIsDrilling then dMaxDepth = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxDepth else dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end dDiamTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM) dDiamTh = EgtTdbGetCurrToolThDiam() end end -- se foro inclinato, limito il massimo affondamento local CosB = abs( vtExtr:getX()) if CosB < BD.DRILL_VX_MAX then local TgA = CosB / sqrt( 1 - CosB * CosB) dMaxDepth = dMaxDepth - dDiamTh / 2 * TgA else dMaxDepth = 0 end -- setto griglia if bSpecialMach then EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdEndPoint], vtExtr)) else EgtSetGridFrame( Frame3d( tFacAdj[nIdLine][nIdIniPoint], vtExtr)) end -- creo geometria local AuxId = EgtCircle( nAddGrpId, {0,0,0}, EgtIf( bIsDrilling, dDiamTool/2, ( dDiamTool/2) + 0.1), GDB_RT.GRID) -- riporto la griglia a globale EgtSetGridFrame() -- calcolo spessore local dDepthBore = dMaxLen if bSpecialMach then -- calcolo l'elevazione local dLenIn, dLedOut = BL.GetPointDirDepth( nPartId, tFacAdj[nIdLine][nIdEndPoint], vtExtr) if dLenIn > 0 then dDepthBore = dLenIn elseif dLedOut then dDepthBore = dLedOut end EgtModifyCurveThickness( AuxId, dDepthBore) else EgtModifyCurveThickness( AuxId, -dMaxLen) end -- inserisco la lavorazione local sName = 'Drill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sDrilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sDrilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.ADIR_YM if vtExtr:getY() > 100 * GEO.EPS_ZERO then nSCC = MCH_SCC.ADIR_YP end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- aggiusto l'affondamento local dDepth if bSpecialMach then dDepth = dDepthBore else dDepth = dMaxLen if dDepth > dMaxDepth + 10 * GEO.EPS_SMALL then sMyWarn = 'Warning in drill : depth (' .. EgtNumToString( dDepth, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' dDepth = dMaxDepth EgtOutLog( sMyWarn) end end EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- Note utente con dichiarazione nessuna generazione sfridi per Vmill local sUserNotes = 'VMRS=0;' -- aggiungo alle note massima elevazione (coincide con affondamento) sUserNotes = sUserNotes .. 'MaxElev=' .. EgtNumToString( dDepth, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) if not 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 else return true, ( sMyWarn or sWarn) end end end return true, sMyWarn end --------------------------------------------------------------------- local function ExtractExternalPaths( nPathInt, nNumIdAux, vtOrtho, b3Solid, nAddGrpId) local nAuxId1, nAuxId2 if nNumIdAux == 1 then -- fondo tra loro le curve compatibili EgtMergeCurvesInCurveCompo( nPathInt) -- esplodo il percorso in modo da avere entià separate per poterle controllare local nStartId, nNumIds = EgtExplodeCurveCompo( nPathInt) if nStartId then local sDeleteByDir -- Se normale lungo la Z elimino le entità che hanno differenza in Z if abs(vtOrtho:getZ()) > 0.7 then sDeleteByDir = 'Z' -- altrimenti se normale lungo la Y elimino le entità che hanno variazione in Y -- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getY()) > 0.7 then elseif abs(vtOrtho:getY()) > 0.7 then sDeleteByDir = 'Y' -- caso che non dovrebbe mai capitare ma gestito per completezza -- altrimenti se normale lungo la X elimino le entità che hanno variazione in X -- elseif abs(vtOrtho:getZ()) < 0.001 and abs(vtOrtho:getX()) > 0.7 then elseif abs(vtOrtho:getX()) > 0.7 then sDeleteByDir = 'X' end if sDeleteByDir then for i = 1, nNumIds do local ptP1 = EgtSP( ( nStartId + i - 1), GDB_RT.GLOB) local ptP2 = EgtEP( ( nStartId + i - 1), GDB_RT.GLOB) if sDeleteByDir == 'Z' then -- se hanno variazione in Z cancello l'entità if abs( ptP1:getZ() - ptP2:getZ()) > 10 * GEO.EPS_SMALL then EgtErase( nStartId + i - 1) end elseif sDeleteByDir == 'Y' then -- se hanno variazione in Y cancello l'entità if abs( ptP1:getY() - ptP2:getY()) > 10 * GEO.EPS_SMALL then EgtErase( nStartId + i - 1) end elseif sDeleteByDir == 'X' then -- se hanno variazione in X cancello l'entità if abs( ptP1:getX() - ptP2:getX()) > 10 * GEO.EPS_SMALL then EgtErase( nStartId + i - 1) end end end -- ricreo i vari percorsi local dLocalVal local tPaths = {} local nNumPaths local dMaxVal local dMinVal for i = 1, nNumIds do local ptP1 = EgtSP( ( nStartId + i - 1), GDB_RT.GLOB) if ptP1 then if sDeleteByDir == 'Z' then local bInsTab for j = 1, #tPaths do local dLocalVal = tPaths[j][2] if abs( ptP1:getZ() - dLocalVal) < 10 * GEO.EPS_SMALL then local tLocIds = tPaths[j][1] table.insert( tLocIds, ( nStartId + i - 1)) tPaths[j][1] = tLocIds bInsTab = true end end -- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella if not bInsTab then table.insert( tPaths, {{( nStartId + i - 1)}, ptP1:getZ()}) dMaxVal = b3Solid:getMax():getZ() dMinVal = b3Solid:getMin():getZ() end elseif sDeleteByDir == 'Y' then local bInsTab for j = 1, #tPaths do local dLocalVal = tPaths[j][2] if abs( ptP1:getY() - dLocalVal) < 10 * GEO.EPS_SMALL then local tLocIds = tPaths[j][1] table.insert( tLocIds, ( nStartId + i - 1)) tPaths[j][1] = tLocIds bInsTab = true end end -- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella if not bInsTab then table.insert( tPaths, {{( nStartId + i - 1)}, ptP1:getY()}) dMaxVal = b3Solid:getMax():getY() dMinVal = b3Solid:getMin():getY() end elseif sDeleteByDir == 'X' then local bInsTab for j = 1, #tPaths do local dLocalVal = tPaths[j][2] if abs( ptP1:getX() - dLocalVal) < 10 * GEO.EPS_SMALL then local tLocIds = tPaths[j][1] table.insert( tLocIds, ( nStartId + i - 1)) tPaths[j][1] = tLocIds bInsTab = true end end -- se non ho trovato da inserirlo aggiungo nuovo elemento in tabella if not bInsTab then table.insert( tPaths, {{( nStartId + i - 1)}, ptP1:getX()}) dMaxVal = b3Solid:getMax():getX() dMinVal = b3Solid:getMin():getX() end end end end if tPaths then local tChamPath = {} -- elimino quelle che non corrispondono agli estremi for i = 1, #tPaths do -- se non corrisponde ai limiti elimino l'elemento if abs( tPaths[i][2] - dMaxVal) > 10 * GEO.EPS_SMALL and abs( tPaths[i][2] - dMinVal) > 10 * GEO.EPS_SMALL then tPaths[i] = nil end end for i = 1, #tPaths do if tPaths[i] then local tNoMatch = {} local tPathLoc = tPaths[i][1] local pIniLoc = EgtSP( tPathLoc[1], GDB_RT.GLOB) local pEndLoc = EgtEP( tPathLoc[1], GDB_RT.GLOB) -- ciclo sui percorsi per trovare i punti non coincidenti (se percorso non chiuso) for j = 2, #tPathLoc do -- prendo i punti del percorso successivo local pAddIni = EgtSP( tPathLoc[j], GDB_RT.GLOB) local pAddEnd = EgtEP( tPathLoc[j], GDB_RT.GLOB) -- se consecutivi if AreSamePointApprox( pEndLoc, pAddIni) then pEndLoc = pAddEnd elseif AreSamePointApprox( pIniLoc, pAddEnd) then pIniLoc = pAddIni else table.insert( tNoMatch, tPathLoc[j]) end end -- controllo eventuali percorsi scartati for j = 1, #tNoMatch do -- prendo i punti del percorso successivo local pAddIni = EgtSP( tNoMatch[j], GDB_RT.GLOB) local pAddEnd = EgtEP( tNoMatch[j], GDB_RT.GLOB) -- se consecutivi if AreSamePointApprox( pEndLoc, pAddIni) then pEndLoc = pAddEnd elseif AreSamePointApprox( pIniLoc, pAddEnd) then pIniLoc = pAddIni end end -- creo concatenamento partendo dal punto iniziale local nIdLoc = EgtCurveCompoByReorder( nAddGrpId, tPathLoc, pIniLoc, true) if nIdLoc then table.insert( tChamPath, nIdLoc) end end end for i = 1, #tChamPath do local ptP1 = EgtSP( tChamPath[i], GDB_RT.GLOB) -- modifico estrusione percorso if sDeleteByDir == 'Z' then if abs(ptP1:getZ() - dMaxVal) < 10 * GEO.EPS_SMALL then EgtModifyCurveExtrusion( tChamPath[i], Z_AX(), GDB_RT.GLOB) else EgtModifyCurveExtrusion( tChamPath[i], -Z_AX(), GDB_RT.GLOB) end elseif sDeleteByDir == 'Y' then if abs(ptP1:getY() - dMaxVal) < 10 * GEO.EPS_SMALL then EgtModifyCurveExtrusion( tChamPath[i], Y_AX(), GDB_RT.GLOB) else EgtModifyCurveExtrusion( tChamPath[i], -Y_AX(), GDB_RT.GLOB) end elseif sDeleteByDir == 'X' then if abs(ptP1:getX() - dMaxVal) < 10 * GEO.EPS_SMALL then EgtModifyCurveExtrusion( tChamPath[i], X_AX(), GDB_RT.GLOB) else EgtModifyCurveExtrusion( tChamPath[i], -X_AX(), GDB_RT.GLOB) end end end if #tChamPath == 1 then return tChamPath[1], 1, nil elseif #tChamPath == 2 then return tChamPath[1], 2, tChamPath[2] else for i = 1, nNumIds do EgtErase( nStartId + i - 1) end for i = 1, #tChamPath do EgtErase( tChamPath[i]) end end else for i = 1, nNumIds do EgtErase( nStartId + i - 1) end end -- altrimenti cancello tutte le emtità e restituisco nil else for i = 1, nNumIds do EgtErase( nStartId + i - 1) end end end end return nil, 0, nil end --------------------------------------------------------------------- local function MakeChamfer( Proc, bIs3Faces, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham) -- Se variabile globale indica che lo smusso è gi stato fatto, esco if bMadeChamfer then return 0 end bMadeChamfer = true -- recupero la lavorazione local sMilling = ML.FindMilling( 'Mark') if not sMilling then local sErr = 'Error : Mark not found in library' EgtOutLog( sErr) return -1, sErr end -- ottengo le curve di contorno libero local nAuxId1, nAuxId2, nNumIdAux if bIs3Faces then -- nAuxId1, _ = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) -- EgtModifyCurveExtrusion( nAuxId1, vtOrtho, GDB_RT.GLOB) -- SetOpenSide( nAuxId1, vtOrtho, b3Solid, nAddGrpId, 1) -- nNumIdAux = 2 -- estraggo i percorsi nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, nAddGrpId) -- se percorso creato estraggo solo i percorsi delle facce interessate, non di testa if nAuxId1 then nAuxId1, nNumIdAux, nAuxId2 = ExtractExternalPaths( nAuxId1, nNumIdAux, vtOrtho, b3Solid, nAddGrpId) end else nAuxId1, nNumIdAux = EgtExtractSurfTmLoops( Proc.Id, nAddGrpId) if not nNumIdAux then nNumIdAux = 0 end end local dExtra = 2 for i = 1, nNumIdAux do local AuxId local vtExtr if bIs3Faces then if i == 1 then AuxId = nAuxId1 else -- faccio la copia del percorso -- AuxId = EgtCopyGlob( nAuxId1, nAddGrpId) AuxId = nAuxId2 end if AuxId then vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) end else AuxId = nAuxId1 + i - 1 vtExtr, _, _ = EgtCurveArea( AuxId) end if vtExtr then if not bIs3Faces then local fFrCurve = EgtGetGlobFrame( AuxId) vtExtr:toGlob( fFrCurve) end -- if bIs3Faces and i == nNumIdAux then -- vtExtr = -vtExtr -- end -- Se normale entro certi limiti -- if vtExtr:getZ() > -0.707 and ( abs(vtOrtho:getX()) > 0.99 or abs(vtOrtho:getY()) > 0.99 or abs(vtOrtho:getZ()) > 0.99) then if vtExtr:getZ() > -0.707 and ( abs(vtExtr:getX()) > 0.99 or abs(vtExtr:getY()) > 0.99 or abs(vtExtr:getZ()) > 0.99) then -- inserisco la lavorazione local sNameCh = 'Cham_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchId = EgtAddMachining( sNameCh, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sNameCh .. '-' .. sMilling EgtOutLog( sErr) return -1, sErr end -- modifico estrusione percorso EgtModifyCurveExtrusion( AuxId, vtExtr, GDB_RT.GLOB) -- aggiungo geometria EgtSetMachiningGeometry( {{ AuxId, -1}}) -- imposto posizione braccio porta testa if vtExtr:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) -- assegno affondamento e offset radiale -- EgtSetMachiningParam( MCH_MP.DEPTH, dDepthCham + dExtra - EgtIf( bIs3Faces, (dDepth / 2), 0)) EgtSetMachiningParam( MCH_MP.DEPTH, dDepthCham + dExtra) EgtSetMachiningParam( MCH_MP.OFFSR, dExtra) -- se opero su 3 facce e sono al secondo e ultimo percorso inverto la lavorazione -- if bIs3Faces and i == nNumIdAux then -- EgtSetMachiningParam( MCH_MP.INVERT, true) -- end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchId, false) return -1, sErr end -- se non perpendicolare emetto un warning -- else -- sWarn = 'Warning : chamfer skipped because not perpendicular to face or from bottom' -- EgtOutLog( sWarn) end --emetto un warning -- else -- sWarn = 'Warning : chamfer skipped because not perpendicular to face' -- EgtOutLog( sWarn) end end return 0 end --------------------------------------------------------------------- local function MakeByChainOrSaw( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dElev, bForceUseBlade, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFacesMaster, nBottomFace, nChamfer, nAddGrpId, b3Solid, dDepthCham, bIs3Faces) local bOrthoFaces local sWarn -- ingombro del grezzo local b3Raw = EgtGetRawPartBBox( nRawId) -- ottengo la distanza tra la fine del pezzo e il pezzo successivo local dDistToNextPiece = EgtGetInfo( nRawId, 'BDST', 'd') or 5.4 if bIs3Faces then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd1, dFacElev1, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, nPartId, bIs3Faces) if not nFacInd1 or nFacInd1 < 0 then if nFacInd1 == -1 then bOrthoFaces = nFacInd2 else local sErr = 'Error : MakeByChainOrSaw could not find reference face' EgtOutLog( sErr) return false, sErr end end else bOrthoFaces = bOrthoFacesMaster end if bOrthoFaces then -- ottengo le dimensioni del tunnel dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = GetTunnelDimension( Proc, nPartId) -- verifico la direzione -- se devo inserire il chamfer if nChamfer > 0 then local nOk, sErr = MakeChamfer( Proc, bIs3Faces, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham) if nOk < 0 then return false, sErr end end end -- Recupero le facce adiacenti alla principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' EgtOutLog( sErr) return false, sErr end EgtOutLog( 'Adjac=' .. table.concat( vAdj, ','), 3) -- Cerco una faccia adiacente alla principale sul lato più lungo local nFacAdj local dMaxLen = 0 for i = 1, #vAdj do if vAdj[i] >= 0 then local _, ptP1, ptP2, _ = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) local dLen = dist( ptP1, ptP2) if dLen > dMaxLen then nFacAdj = vAdj[i] dMaxLen = dLen EgtOutLog( string.format( 'Adjac=%d Len=%.3f H=%.3f V=%.3f', vAdj[i], dLen, dH, dV), 3) end end end if not nFacAdj then local sErr = 'Error : long adjacent face not found' EgtOutLog( sErr) return false, sErr end -- Riordino le dimensioni per avere dH come lato lungo e dV come perpendicolare local _, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacAdj, GDB_ID.ROOT) if abs( vtN * rfFac:getVersX()) > abs( vtN * rfFac:getVersY()) then dH, dV = dV, dH end -- Determino se estremi aperti o chiusi local bOpenStart = false local bOpenEnd = false local vtNS, vtNE -- se non ho la faccia di fondo ( che comporta essere una fessura) verifico se ho lati aperti if not nBottomFace then local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, nFacAdj)[1] EgtOutLog( 'Adj2=' .. table.concat( vAdj2, ' ,'), 3) for j = 1, #vAdj2 do if vAdj2[j] == nFacInd then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == nFacInd do i = EgtIf( i > 1, i - 1, #vAdj2) end bOpenStart = ( vAdj2[i] < 0) -- se è chiusa acquisisco vettore faccia tappo if not bOpenStart and vAdj2[i] >= 0 then _, vtNS = EgtSurfTmFacetCenter( Proc.Id, vAdj2[i], GDB_ID.ROOT) end -- Se non esiste faccia adiacente a lato successivo -> fine aperto local k = EgtIf( j < #vAdj2, j + 1, 1) while vAdj2[k] == nFacInd do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) -- se è chiusa acquisisco vettore faccia tappo if not bOpenEnd and vAdj2[k] >= 0 then _, vtNE = EgtSurfTmFacetCenter( Proc.Id, vAdj2[k], GDB_ID.ROOT) end end end end -- Recupero il massimo affondamento possibile con la lama local dSawMaxDepth = 0 local sCutting = ML.FindCutting( 'HeadSide') if sCutting then if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawMaxDepth = EgtTdbGetCurrToolMaxDepth() or dSawMaxDepth end end end -- Se entrambi gli estremi sono aperti e possibile, lavoro con la lama if bOpenStart and bOpenEnd and bForceUseBlade and dElev < dSawMaxDepth + 10 * GEO.EPS_SMALL then -- Recupero la lavorazione di lama local sCutting = ML.FindCutting( 'HeadSide') if not sCutting then local sErr = 'Error : HeadSide (cutting) not found in library' EgtOutLog( sErr) return false, sErr, 'MNF' end -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 4 if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick end end if dSawThick > dV + 10 * GEO.EPS_SMALL then local sErr = 'Error : sawblade too thick' EgtOutLog( sErr) return false, sErr end -- Calcolo uso faccia local nFaceUse = BL.GetNearestOrthoOpposite( rfFac:getVersZ()) -- Eseguo i tagli local nStep = ceil( ( dV - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dV - dSawThick) / ( nStep - 1) end for i = 1, nStep do local dOffs = ( i - 1) * dStep local bOk, sErr = BL.MakeOneFaceBySaw( Proc.Id, nFacAdj, sCutting, dSawDiam, nFaceUse, -0.01, 0, BD.CUT_SIC, dOffs, 0, 0, nil, b3Raw) if not bOk then return bOk, sErr end end -- in base all'elevazione calcolo l'impronta della lama local dUsedBladeLen = sqrt( ((dSawDiam / 2)*(dSawDiam / 2)) - ( ( (dSawDiam / 2) - dElev) * ( (dSawDiam / 2) - dElev))) -- controllo direzione taglio e se il minimo della feature sborda in coda if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL and dDistToNextPiece < dUsedBladeLen then -- do avviso che la lama può sbordare nel pezzo successivo sWarn = 'Warning on saw cut : Cut machining can damage next piece' EgtOutLog( sWarn .. ' (process ' .. tostring( Proc.Id) .. ')') end -- altrimenti con sega a catena else -- Recupero la lavorazione local sSawing = ML.FindSawing( 'Sawing') if not sSawing then local sErr = 'Error : Sawing not found in library' EgtOutLog( sErr) return false, sErr, 'MNF' end -- Recupero i dati dell'utensile local dSawWidth = 75 local dSawThick = 8 local dMaxDepth = 200 if EgtMdbSetCurrMachining( sSawing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawWidth = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawWidth dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end if dSawThick > dV + 10 * GEO.EPS_SMALL then local sErr = 'Error : chainsaw too thick' EgtOutLog( sErr) return false, sErr end local bGoFromHead = true -- se la lunghezza utensile non riesce ad arrivare sul fondo assegno la possibilità di lavorare di testa o di fianco if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then -- lavora di testa se è un tunnel, lavora di fianco se non è un tunnel bGoFromHead = not bOrthoFaces end -- se continuo a lavorare di testa if bGoFromHead then -- Calcolo uso faccia local nFaceUse = BL.GetNearestParalOpposite( rfFac:getVersZ()) -- Calcolo normale faccia adiacente local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacAdj, GDB_ID.ROOT) -- Verifico se necessarie più passate local nStep = ceil( ( dV - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dV - dSawThick) / ( nStep - 1) end for i = 1, nStep do -- Applico la lavorazione con sega a catena a questa faccia local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchFId = EgtAddMachining( sName, sSawing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacAdj}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- controllo direzione taglio e se il minimo della feature sborda in coda if not Proc.Tail and abs( vtN:getX()) < GEO.EPS_SMALL and abs( b3Solid:getMin():getX() - Proc.Box:getMin():getX()) < 100 * GEO.EPS_SMALL then -- se ho lato partenza aperto e lato uscita chiuso e direzione lato chiuso è negativa, allora controllo uscita lama if bOpenStart and not bOpenEnd and vtNE:getX() < -0.99 and dDistToNextPiece < (dSawWidth / 2) then -- imposto accorciamento iniziale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.STARTADDLEN, dDistToNextPiece - 1 - (dSawWidth / 2)) else -- imposto accorciamento iniziale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2)) end -- se ho lato uscita aperto e lato partenza chiuso e direzione lato partenza è negativa, allora controllo uscita lama if bOpenEnd and not bOpenStart and vtNS:getX() < -0.99 and dDistToNextPiece < (dSawWidth / 2) then -- imposto accorciamento finale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.ENDADDLEN, dDistToNextPiece - 1 - (dSawWidth / 2)) else -- imposto accorciamento finale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2)) end else -- imposto accorciamento iniziale/finale per estremi aperti/chiusi EgtSetMachiningParam( MCH_MP.STARTADDLEN, EgtIf( bOpenStart, 0, - dSawWidth / 2)) EgtSetMachiningParam( MCH_MP.ENDADDLEN, EgtIf( bOpenEnd, 0, - dSawWidth / 2)) end -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1)) -- imposto offset radiale local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- se necessario, limito l'affondamento if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then sWarn = 'Warning in LapJoint : elevation (' .. EgtNumToString( dElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' dDepth = dMaxDepth - dElev EgtOutLog( sWarn) EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH '..EgtNumToString( dDepth, 1)) end -- imposto elevazione local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 2) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then if EgtGetOutstrokeInfo() then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2)) if BD.C_SIMM then if vtN:getY() > 0 then EgtSetMachiningParam( MCH_MP.INITANGS, 'C=180') else EgtSetMachiningParam( MCH_MP.INITANGS, 'C=-180') end end if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end if EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end end -- altrimenti segacatena di fianco else -- verifico se posso farlo con la sega-catena local bMakeChainSaw, sSawing2, dMaxMat2, dSawCornerRad2, dSawThick2 = VerifyChainSaw( Proc, dDimMin, dDimMax, vtOrtho) if bMakeChainSaw then -- Verifico se necessarie più passate local nStep = ceil( ( dDimMin - 10 * GEO.EPS_SMALL) / dSawThick2) local dStep = 0 if nStep > 1 then dStep = ( dDimMin - dSawThick2) / ( nStep - 1) end for i = 1, nStep do -- inserisco la lavorazione di sawing local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchFId = EgtAddMachining( sName, sSawing2) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing2 EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nLundIdFace}}) -- imposto uso del lato faccia -- al momento, dato che la fessura è passante da parte a parte, gestisco solo la lavorazione -- dall'alto e di fronte (da dietro è disabilitata perchè ho exracorsa con la FAST). -- Questa feature non è applicata su facce di testa e quindi non controllo l'entrata in X if abs(vtOrtho:getZ()) >= 0.707 then EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) --elseif abs(vtOrtho:getZ()) < 0.707 and abs(vtOrtho:getY()) > 0.707 then else EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_BACK) --elseif abs(vtOrtho:getZ()) <= 0.707 and vtOrtho:getY() < -0.707 then -- EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_FRONT) --elseif abs(vtOrtho:getZ()) < 0.707 and vtOrtho:getX() > 0.707 then -- EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_LEFT) --else -- EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_RIGHT) end -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1)) -- imposto offset radiale local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- se possibile aumento l'affondamento pari al raggio corner + 1 if dMaxMat2 > (dDepth + dSawCornerRad2 + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dDepth + dSawCornerRad2 + 1)) -- se massimo affondamento supera altezza fessura, uso massimo affondamento elseif dMaxMat2 > (dDepth + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dMaxMat2 - 1)) -- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning elseif dMaxMat2 < dDepth then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat2) sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- eseguo if not EgtApplyMachining( true, false) then if EgtGetOutstrokeInfo() then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2)) if BD.C_SIMM then local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nLundIdFace, GDB_ID.ROOT) if vtN:getY() > 0 then EgtSetMachiningParam( MCH_MP.INITANGS, 'C=180') else EgtSetMachiningParam( MCH_MP.INITANGS, 'C=-180') end end if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end if EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end end end end end return true, sWarn end --------------------------------------------------------------------- local function MakeAntiSplintBySaw( Proc, nFacet, vtN, b3Raw, nFacInd, bReduceDepth) -- Recupero la lavorazione di lama local sCutting = ML.FindCutting( 'HeadSide') if not sCutting then local sErr = 'Error : HeadSide (cutting) not found in library' EgtOutLog( sErr) return false, sErr end -- valuto l'angolo tra le due facce local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacet, GDB_ID.ROOT) local ptPm = (ptP1+ptP2)/2 -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta l'elevazione della faccia -- laterale sul punto medio della linea in comune local frFc = Frame3d( ptPm, vtN) ; local bBoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc) dDepth = bBoxLoc:getDimZ() or 0 -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 0 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end local dExtraOffs = 0 -- se profondità superiore al massimo lama modifico elevazione if dDepth > dMaxDepth then dExtraOffs = dMaxDepth - dDepth end -- se devo ridurre l'affondamento if bReduceDepth then local dLimitDepth = 100 -- se ho ridotto l'affondamento ne riduco ulteriormente l'affondamento (50mm) if abs(dExtraOffs) > 0 then if dMaxDepth > dLimitDepth then dExtraOffs = dLimitDepth - dDepth end else if dDepth > dLimitDepth then dExtraOffs = dLimitDepth - dDepth else dExtraOffs = - (dDepth/2) end end end -- eseguo il taglio local bMadeASbyBld, sWarn, nIdMach = BL.MakeOneFaceBySaw( Proc.Id, nFacet, sCutting, dSawDiam, vtN, nil, ( -0.5 + dExtraOffs), BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if bMadeASbyBld then sWarn = nil if abs(dExtraOffs) > 0 then sWarn = 'Warning : antisplint elevation is bigger than max tool depth' end end return bMadeASbyBld, sWarn, nIdMach, dSawThick, dMaxDepth, bAdj, dAng, dExtraOffs end --------------------------------------------------------------------- local function MakePocket( Proc, nPartId, ptPs, tvtN, nFaceRef, sMchFind, nUseRoughTool, sMasterPocket, dPrevFaceElev, tDimAndRef, dAng) -- calcolo l'elevazione dal punto medio local dElev local dLenIn, dLedOut = BL.GetPointDirDepth( nPartId, ptPs, tvtN[2]) if dLenIn > 0 then dElev = dLenIn elseif dLedOut then dElev = dLedOut end local dCollSic = 2 * BD.COLL_SIC -- calcolo il diametro utensile local dDiamTool local dFaceDiamTool if tDimAndRef then -- prendo il valore dalle dimensioni minime delle facce dFaceDiamTool = min( tDimAndRef[2][1], tDimAndRef[2][2]) end -- se ho lavorazione precedente ricalcolo grossolanamente l'elevazione if dPrevFaceElev and dPrevFaceElev > 0 and dAng then dElev = dElev + ( sqrt( ( dElev * dElev) - ( dPrevFaceElev * dPrevFaceElev)) * sin(dAng)) elseif dPrevFaceElev and dPrevFaceElev > dElev then dElev = dPrevFaceElev end local sPocketing if sMasterPocket then sPocketing = sMasterPocket else sPocketing = ML.FindPocketing( sMchFind, dFaceDiamTool, dElev + dCollSic) end if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr end dDiamTool = 20 local dMaxDepth = 0 local sTuuidPk if EgtMdbSetCurrMachining( sPocketing) then sTuuidPk = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuidPk) or '') then dMaxDepth = ( EgtTdbGetCurrToolMaxDepth() or dMaxDepth) dDiamTool = EgtTdbGetCurrToolParam( MCH_TP.DIAM) end end -- se nome svuotatura non è stato ricalcolato, confronto il diametro utensile utilizzato con il minimo faccia e se non sono compatibili esco if sMasterPocket and dFaceDiamTool and dDiamTool >= dFaceDiamTool then return false, '', sTuuidPk, dDiamTool, dElev end -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. 'F' .. tostring( nFaceRef) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, (nFaceRef)}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = MCH_SCC.ADIR_YM if AreSameVectorApprox( tvtN[2], Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( tvtN[2]:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( EgtGetCurrPhase()), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif tvtN[2]:getY() > 0.1 then nSCC = MCH_SCC.ADIR_YP end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta e non lavorata col truciolatore, imposto opportuno attacco if sMchFind == 'OpenPocket' and nUseRoughTool == 0 then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente local sWarn if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxDepth - dElev) dElev = dMaxDepth sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true, sWarn, sTuuidPk, dDiamTool end --------------------------------------------------------------------- local function MachineByMill( Proc, nPhase, nRawId, nPartId, b3Solid, tvtN, nBaseFace, nSideFace, ptPs, tDimAndRef, b3Raw, nDiffWidth, nUseRoughTool, dAng, sPocketing, sTuuidPk, dPrevFaceElev) local sMchFind = 'Pocket' local dAngLimit = 40 -- se feature é larga come trave imposto openpocket if nDiffWidth == 0 then sMchFind = 'OpenPocket' -- altrimenti non è passante disabilito il truciolatore else nUseRoughTool = 0 end -- se angolo tra le facce maggiore di 90, inserisco la contornatura o svuotatura del lato più corto if ( 180 + dAng) > 90.1 then -- calcolo l'angolo dalla verticale dall'angolo tra le due facce, perchè la feature potrebbe essere ruotata sulla Z locale della -- faccia principale e quindi la componente X del versore della faccia potrebbe dare un valore non coerente local dDiffFromSqAng = dAng + 90 -- se l'angolo dalla verticale si discosta di più dell'angolo limite impostato, utilizzo la svuotatura if cos( dDiffFromSqAng) < cos( dAngLimit) then -- applico la svuotatura local bOk, sWarn, sTuuidPk, dDiamTool, dElev = MakePocket( Proc, nPartId, ptPs, tvtN, nSideFace, sMchFind, nUseRoughTool, sPocketing, dPrevFaceElev, tDimAndRef, dAng) if not bOk then -- se ho id utensile e diametro è perchè non ha fatto svuotatura perchè la faccia è più stretta del diametro utensile -- e provo ad inserire singola passata di testa if sTuuidPk and dDiamTool then -- recupero la lavorazione local sMilling = ML.FindMilling( 'Long2Cut', dElev, sTuuidPk) if not sMilling then local sErr = 'Error : Long2Cut not found in library' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione local sName = 'Prof_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchId = EgtAddMachining( sName, sMilling) if not nMchId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nSideFace}}) -- imposto uso faccia local nFaceUse = BL.GetNearestOrthoOpposite(tvtN[1]) -- aggiusto i parametri EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) EgtSetMachiningParam( MCH_MP.DEPTH_STR, 'TH') EgtSetMachiningParam( MCH_MP.OFFSR, 0) EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, 1) -- imposto posizione braccio porta testa if tvtN[2]:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end else return false, sWarn end else return bOk, sWarn end -- altrimenti contornatura di fianco else local bOpenStart = false local bOpenEnd = false if nDiffWidth == 0 then bOpenStart = true bOpenEnd = true else local vAdj2 = EgtSurfTmFacetAdjacencies( Proc.Id, (nBaseFace))[1] for j = 1, #vAdj2 do if vAdj2[j] == (nSideFace) then -- Se non esiste faccia adiacente a lato precedente -> inizio aperto local i = EgtIf( j > 1, j - 1, #vAdj2) while vAdj2[i] == (nSideFace) do i = EgtIf( i > 1, i - 1, #vAdj2) end bOpenStart = ( vAdj2[i] < 0) -- Se non esiste faccia adiacente a lato successivo -> fine aperto local k = EgtIf( j < #vAdj2, j + 1, 1) while vAdj2[k] == (nSideFace) do k = EgtIf( k < #vAdj2, k + 1, 1) end bOpenEnd = ( vAdj2[k] < 0) end end end local sMilling if nUseRoughTool > 0 then sMilling = ML.FindMilling( 'Long2Cut', nil, sTuuidPk) else sMilling = ML.FindMilling( 'LongSmallCut', nil, sTuuidPk) end if not sMilling then local sErr = 'Error : Long2Cut & LongSmallCut not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dTDiam = 50 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dTDiam end end -- Calcolo uso faccia local nFaceUse = BL.GetNearestParalOpposite( tDimAndRef[1][3]:getVersZ()) -- inserisco la lavorazione di fresatura local sName = 'Mill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, (nSideFace)}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- setto inversione del percorso EgtSetMachiningParam( MCH_MP.INVERT, true) -- setto a 0 eventuali offset EgtSetMachiningParam( MCH_MP.OFFSR, 0) -- calcolo elevazione per allungamenti attacchi con fianchi chiusi local dElev local dLenIn, dLedOut = BL.GetPointDirDepth( nPartId, ptPs, tvtN[2]) if dLenIn > 0 then dElev = dLenIn elseif dLedOut then dElev = dLedOut end -- applico gli allungamenti o accorciamenti if bOpenStart then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dTDiam / 2) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, -dTDiam / 2) if dElev > 0 then EgtSetMachiningParam( MCH_MP.LIPERP, dElev) end end if bOpenEnd then EgtSetMachiningParam( MCH_MP.ENDADDLEN, dTDiam / 2) else EgtSetMachiningParam( MCH_MP.ENDADDLEN, -dTDiam / 2) if dElev > 0 then EgtSetMachiningParam( MCH_MP.LOPERP, dElev) end end -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end return true end --------------------------------------------------------------------- local function GetUShapeWidth( Proc, nFacInd) -- Recupero le facce adiacenti alla principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] -- se non ho facce adiacenti esco subito if not vAdj or #vAdj == 0 then return nil end -- Normale della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) -- Cerco le facce adiacenti alla principale con angolo concavo >= 90 local dWidth = 0 for i = 1, #vAdj do if vAdj[i] >= 0 then -- verifico l'angolo tra le facce ( esco se angolo compreso < 90) local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) if bAdj and dAng < -90 - 20 * GEO.EPS_ANG_SMALL then return nil end -- larghezza della faccia ortogonalmente alla adiacente local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, vAdj[i], GDB_ID.ROOT) local vtX = vtN2 ^ vtN local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2) local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef) if b3Ref then dWidth = max( dWidth, b3Ref:getDimY()) end end end return dWidth end --------------------------------------------------------------------- local function MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMchFindMaster, bIs3Faces, b3Solid, bOrthoFacesMaster) local bOrthoFaces local sWarn local sMchFind = 'Pocket' local dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt local bBadMach = false if sMchFindMaster and #sMchFindMaster > 0 then sMchFind = sMchFindMaster end if bIs3Faces then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, nPartId, bIs3Faces) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bOrthoFaces = nFacInd2 else local sErr = 'Error : MakeByPockets could not find reference face' EgtOutLog( sErr) return -1, sErr end end else bOrthoFaces = bOrthoFacesMaster end -- se è un tunnel verifico se è possibile usare la svuotatura if bOrthoFaces then -- ottengo le dimensioni del tunnel dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, nSurfInt = GetTunnelDimension( Proc, nPartId) local nPathInt -- se devo inserire il chamfer if nChamfer > 0 then local nOk, sErr = MakeChamfer( Proc, bIs3Faces, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham) if nOk < 0 then return -1, sErr end end -- se smusso non è esclusivo if nChamfer < 2 then -- verifico se può essere fatto con svuotatura local bMakePocket, sPocketing, dMaxDepth, dDiamTool = VerifyIfPocket( Proc, dDimMin, vtOrtho, dDepth / 2, sMchFind) if bMakePocket then -- gestione svuotatura da un solo lato o anche dal lato opposto (se non verticale) -- estraggo il contorno dalla superfice per evitare i problemi con la svuotatura -- e assegno l'estrusione nPathInt = EgtExtractSurfTmLoops( nSurfInt, nAddGrpId) EgtModifyCurveExtrusion( nPathInt, vtOrtho, GDB_RT.GLOB) -- se ho 3 facce, ciclo sulle entià del percorso per segnare quelle che sono aperte if bIs3Faces then SetOpenSide( nPathInt, vtOrtho, b3Solid, nAddGrpId) end -- variabili per parametri lavorazione local dMachDepth local dElev = 0 local bDoubleSide local bOneShot local bComplete = true -- imposto altezza aggiuntiva di elevazione local dCollSic = CalcCollisionSafety( vtOrtho) -- se possibile svuotare completamente da una sola parte if dMaxDepth > ( dDepth + BD.CUT_EXTRA + dCollSic) then dMachDepth = ( dDepth / 2) + BD.CUT_EXTRA dElev = dDepth + BD.CUT_EXTRA bOneShot = true else -- se direzione verso la verticale setto max affondamento possibile ed -- emetto messaggio di warning perché non lavorabile interamente if abs( vtOrtho:getZ()) >= 0.707 then dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic dElev = dMaxDepth sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) bComplete = false -- altrimenti setto il flag per fare la svuotatura da due parti else -- se l'altezza utensile riesce a lavorare completamente da due parti if dMaxDepth > ( dDepth / 2) + dCollSic + BD.CUT_EXTRA_MIN then dMachDepth = BD.CUT_EXTRA_MIN dElev = ( dDepth / 2) + BD.CUT_EXTRA_MIN -- altrimenti non si riesce in due passate, limito la profondità e setto l'elevazione else dMachDepth = dMaxDepth - ( dDepth / 2) - dCollSic dElev = dMaxDepth -- se molto inclinato rispetto alla normale della faccia di riferimento, lavorazione non idonea per probabili collisioni local vtRef = Y_AX() if abs( vtOrtho:getX()) > abs( vtOrtho:getY()) and abs( vtOrtho:getX()) > abs( vtOrtho:getZ()) then vtRef = X_AX() elseif abs( vtOrtho:getZ()) > abs( vtOrtho:getX()) and abs( vtOrtho:getZ()) > abs( vtOrtho:getY()) then vtRef = Z_AX() end if abs( vtOrtho * vtRef) < 0.5 then bBadMach = true end end bDoubleSide = true end end -- se lavorazione non idonea esco if bIs3Faces and bBadMach then local sErr = 'Impossible apply perpendicular pocketing: ' .. sPocketing return -2, sErr end -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return -1, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ nPathInt, -1}}) -- verifico se devo invertire direzione utensile (in caso di direzione verso la verticale) local bInvertMach if vtOrtho:getZ() < BD.NZ_MINA and abs(vtOrtho:getZ()) >= 0.707 then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true -- altrimenti se da fare in una sola volta e direzionato verso Y+ lo inverto per lavorarlo davanti elseif not bDoubleSide and vtOrtho:getY() > GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvertMach = true end -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtOrtho, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtOrtho:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtOrtho:getY() < GEO.EPS_SMALL then nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = EgtIf( bInvertMach, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- inverto il percorso di lavorazione per lavorare sinistro EgtSetMachiningParam( MCH_MP.INVERT, true) -- imposto affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return -1, sErr end end -- se posso applicare la svuotatura sul lato opposto if bDoubleSide then -- se anche lavorando dal lato opposto non riesco a svuotare completamente la fessura -- setto i parametri affondamento ed emetto warning if 2 * dMaxDepth < dDepth + 2 * BD.CUT_EXTRA + 2 * dCollSic then dMachDepth = dMaxDepth - (dDepth / 2) dElev = dMaxDepth bComplete = false sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- inserisco la lavorazione di svuotatura local sName = 'PockOppo_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return -1, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ nPathInt, -1}}) -- imposto direzione utensile opposta EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameVectorApprox( vtOrtho, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtOrtho:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtOrtho:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YP else nSCC = MCH_SCC.ADIR_YM end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- inverto il percorso di lavorazione per lavorare sinistro EgtSetMachiningParam( MCH_MP.INVERT, true) -- imposo affondamento EgtSetMachiningParam( MCH_MP.DEPTH, dMachDepth) -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return -1, sErr end end end -- se non completo e U, cerco di lavorare anche la faccia di fondo (con il massimo affondamento possibile) if not bComplete and bIs3Faces then -- recupero la faccia da lavorare local nFacInd = BL.GetFaceWithMostAdj( Proc.Id, nPartId) local vtN local bPock3rd = false if nFacInd then vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) bPock3rd = ( vtN and vtN:getZ() >= BD.NZ_MINA) end if bPock3rd then -- inserisco la lavorazione di svuotatura local sName = EgtIf( bDoubleSide, 'Pock3rd_', 'Pock2nd_') .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return -1, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto posizione braccio porta testa local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if AreSameOrOppositeVectorApprox( vtN, Z_AX()) then nSCC = MCH_SCC.ADIR_YM elseif abs( vtN:getX()) < 0.1 then nSCC = EgtIf( BL.IsPartFinalPhase( nPhase), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) elseif vtN:getY() < GEO.EPS_SMALL then nSCC = MCH_SCC.ADIR_YM else nSCC = MCH_SCC.ADIR_YP end end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- inverto il percorso di lavorazione per lavorare sinistro EgtSetMachiningParam( MCH_MP.INVERT, true) -- imposto affondamento EgtSetMachiningParam( MCH_MP.DEPTH, 0) -- dichiaro non si generano sfridi per VMill local sNotes = 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return -1, sErr end end end end return 1, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot end end end return 0, sWarn, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bOrthoFaces end --------------------------------------------------------------------- local function ManageAntiSplintBySaw( Proc, b3Raw, bIsU, vtN, nFacet, nFacInd, sWarn, bReduceDepth) local bMadeASbyBld = false local nNumFac = EgtIf( bIsU, 2, 1) local nPrefSide = 1 -- di preferenza il motore è meglio tenerlo sinistra -- se a U cerco di ottimizzare il lato di lavoro della lama if bIsU then if abs( vtN:getY()) > 0.996 then nPrefSide = 0 elseif abs( vtN:getZ()) > 0.63 or abs( vtN:getY()) > 0.63 then -- elseif abs( vtN:getZ()) > 0.7 or abs( vtN:getY()) > 0.7 then -- se X è negativa allora devo tenere il motore a destra if vtN:getX() < -(10 * GEO.EPS_SMALL) then nPrefSide = 2 end end end -- va eseguito sulle facce diverse dalla principale local nPrevSCC = nil for nFacet = 0, nNumFac do if nFacet ~= nFacInd then -- lavoro local dSawThick = 0 local dMaxDepth = 200 local bAdj, dAng, dExtraOffs, sWarn2, nIdMach bMadeASbyBld, sWarn2, nIdMach, dSawThick, dMaxDepth, bAdj, dAng, dExtraOffs = MakeAntiSplintBySaw( Proc, nFacet, vtN, b3Raw, nFacInd, bReduceDepth) if not bMadeASbyBld then return bMadeASbyBld, false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = sWarn .. '\n' .. sWarn2 end -- se antischeggia veramente inserito perchè necessario if nIdMach then -- verifico se da invertire local bInvertMach = false local dDepth = 0 if bIsU then if abs(vtN:getZ()) > 0.63 or abs(vtN:getY()) > 0.63 then -- if abs(vtN:getZ()) > 0.7 or abs(vtN:getY()) > 0.7 then -- prendo il vettore normale alla faccia local _, vtNFc = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) -- se superficie principale parallela al piano XZ if nPrefSide == 0 then -- se facce inclinate \\ allora mandrino a destra (per essere verso l'alto) if vtNFc:getX() * vtNFc:getZ() > 0 then nPrefSide = 2 -- altrimenti facce inclinate // quindi mandrino a sinistra (per essere ancora verso l'alto) else nPrefSide = 1 end end -- se faccia verso X+ e mandrino verso sinistra if vtNFc:getX() > 0 and nPrefSide == 1 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end -- se faccia verso X- e mandrino verso destra elseif vtNFc:getX() < 0 and nPrefSide == 2 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end end end end -- eseguo inversione if bInvertMach then local bToolInvert = EgtGetMachiningParam( MCH_MP.TOOLINVERT) local nWS = EgtGetMachiningParam( MCH_MP.WORKSIDE) local nInvWS = EgtIf( nWS == MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT) local nFaceUse = EgtGetMachiningParam( MCH_MP.FACEUSE) local bOrtUp = ( nFaceUse >= MCH_MILL_FU.ORTUP_DOWN and nFaceUse <= MCH_MILL_FU.ORTUP_RIGHT) if not bOrtUp then -- assegno i parametri invertiti EgtSetMachiningParam( MCH_MP.WORKSIDE, nInvWS) EgtSetMachiningParam( MCH_MP.TOOLINVERT, not bToolInvert) -- setto l'offset pari allo spessore lama EgtSetMachiningParam( MCH_MP.OFFSL, -dSawThick) end end -- posizione del braccio : se primo taglio la recupero, altrimenti la imposto if not nPrevSCC then nPrevSCC = EgtGetMachiningParam( MCH_MP.SCC) else EgtSetMachiningParam( MCH_MP.SCC, nPrevSCC) end -- rieseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nIdMach, false) return false, false, sErr end end end end return bMadeASbyBld, true, sWarn end --------------------------------------------------------------------- local function ManageAntiSplintByDrill( Proc, b3Raw, bIsU, vtN, vtN1, nFacet, nFacInd, sWarn) local bMadeASbyBld = false local nNumFac = EgtIf( bIsU, 2, 1) -- va eseguito sulle facce diverse dalla principale local nPrevSCC = nil for nFacet = 0, nNumFac do if nFacet ~= nFacInd then -- lavoro local dSawThick = 0 local dMaxDepth = 200 local bAdj, dAng, dExtraOffs, sWarn2, nIdMach bMadeASbyBld, sWarn2, nIdMach, dSawThick, dMaxDepth, bAdj, dAng, dExtraOffs = MakeAntiSplintBySaw( Proc, nFacet, vtN, b3Raw, nFacInd, bReduceDepth) if not bMadeASbyBld then return bMadeASbyBld, false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = sWarn .. '\n' .. sWarn2 end -- se antischeggia veramente inserito perchè necessario if nIdMach then -- verifico se da invertire local bInvertMach = false local dDepth = 0 if bIsU then if abs(vtN:getZ()) > 0.63 or abs(vtN:getY()) > 0.63 then -- if abs(vtN:getZ()) > 0.7 or abs(vtN:getY()) > 0.7 then -- prendo il vettore normale alla faccia local _, vtNFc = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) -- se superficie principale parallela al piano XZ if nPrefSide == 0 then -- se facce inclinate \\ allora mandrino a destra (per essere verso l'alto) if vtNFc:getX() * vtNFc:getZ() > 0 then nPrefSide = 2 -- altrimenti facce inclinate // quindi mandrino a sinistra (per essere ancora verso l'alto) else nPrefSide = 1 end end -- se faccia verso X+ e mandrino verso sinistra if vtNFc:getX() > 0 and nPrefSide == 1 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end -- se faccia verso X- e mandrino verso destra elseif vtNFc:getX() < 0 and nPrefSide == 2 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end end end end -- eseguo inversione if bInvertMach then local bToolInvert = EgtGetMachiningParam( MCH_MP.TOOLINVERT) local nWS = EgtGetMachiningParam( MCH_MP.WORKSIDE) local nInvWS = EgtIf( nWS == MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT) local nFaceUse = EgtGetMachiningParam( MCH_MP.FACEUSE) local bOrtUp = ( nFaceUse >= MCH_MILL_FU.ORTUP_DOWN and nFaceUse <= MCH_MILL_FU.ORTUP_RIGHT) if not bOrtUp then -- assegno i parametri invertiti EgtSetMachiningParam( MCH_MP.WORKSIDE, nInvWS) EgtSetMachiningParam( MCH_MP.TOOLINVERT, not bToolInvert) -- setto l'offset pari allo spessore lama EgtSetMachiningParam( MCH_MP.OFFSL, -dSawThick) end end -- posizione del braccio : se primo taglio la recupero, altrimenti la imposto if not nPrevSCC then nPrevSCC = EgtGetMachiningParam( MCH_MP.SCC) else EgtSetMachiningParam( MCH_MP.SCC, nPrevSCC) end -- rieseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nIdMach, false) return false, false, sErr end end end end return bMadeASbyBld, true, sWarn end --------------------------------------------------------------------- local function MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, bSinglePart) local sWarn -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) -- recupero l'ingombro della trave local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end local bClosedOrthoFaces local nFacInd, dFacElev, nFacInd2, dFacElev2 local nBottomFace local sMchFindBackUp -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( Proc.Id, nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 else local sErr = 'Error : MakeMoreFaces could not find reference face' EgtOutLog( sErr) return false, sErr end end -- se è una feature scanalatura (con 5 facce) e non è stata riconosciuta come fessura, eseguo altre verifiche if Proc.Prc == 16 and Proc.Fct == 5 and not bClosedOrthoFaces then -- dalla copia della superfice, ciclo eliminando una faccia per volta per verificare se trova fessura for i = 1, Proc.Fct do local nNewProc = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL -- elimino una faccia nBottomFace = i-1 if EgtSurfTmRemoveFacet( nNewProc, nBottomFace) then -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa nFacInd, dFacElev, nFacInd2, dFacElev2 = BL.GetFaceWithMostAdj( nNewProc, nPartId) if not nFacInd or nFacInd < 0 then if nFacInd == -1 then bClosedOrthoFaces = nFacInd2 EgtErase( nNewProc) break else EgtErase( nNewProc) local sErr = 'Error : MakeMoreFaces could not find reference face' EgtOutLog( sErr) return false, sErr end end -- altrimenti esco else EgtErase( nNewProc) break end end -- se riconosciuta fessura ricalcolo l'elevazione dalla faccia di fondo if bClosedOrthoFaces then nFacInd = nBottomFace -- rendo nulla la faccia opzionale perchè si tratta di una fessura nFacInd2 = nil dFacElev = BL.GetFaceElevation( Proc.Id, nFacInd) bClosedOrthoFaces = false -- non setto come tunnel end end -- verifico se sono presenti i parametri Q per la profondità smusso e -- per eseguire in esclusiva solo lo smusso local nChamfer, dDepthCham, sErrCham, bForceUseBlade = EvaluateQParam( Proc) -- se non posso lavorare la feature perché condizionata dall'esecuzione del solo chamfer -- genero errore e non faccio nulla if nChamfer < 0 then return false, sErrCham end -- se è un tunnel provo a vedere se è possibile lavorarlo con la svuotatura o con la sega catena if bClosedOrthoFaces then local bTryWithBlades = true -- lavoro fessura con svuotature (singola o doppia contrapposta) local sMyMchFind = 'Pocket' local nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace = MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMyMchFind, false, b3Solid, bClosedOrthoFaces) if nOk < 0 then return false, sErr elseif nOk > 0 then bTryWithBlades = false end -- Se la svuotatura precedente non è stata fatta e chamfer non è mutuamente esclusivo provo con la sega-catena if bTryWithBlades and nChamfer < 2 then -- verifico se posso farlo con la sega-catena local bMakeChainSaw, sSawing, dMaxMat, dSawCornerRad, dSawThick = VerifyChainSaw( Proc, dDimMin, dDimMax, vtOrtho) if bMakeChainSaw then -- Verifico se necessarie più passate local nStep = ceil( ( dDimMin - 10 * GEO.EPS_SMALL) / dSawThick) local dStep = 0 if nStep > 1 then dStep = ( dDimMin - dSawThick) / ( nStep - 1) end for i = 1, nStep do -- inserisco la lavorazione di sawing local sName = 'Csaw_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( i) local nMchFId = EgtAddMachining( sName, sSawing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sSawing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nLundIdFace}}) -- imposto uso del lato faccia -- al momento, dato che la fessura è passante da parte a parte, gestisco solo la lavorazione -- dall'alto e di fronte (da dietro è disabilitata perchè ho exracorsa con la FAST). -- Questa feature non è applicata su facce di testa e quindi non controllo l'entrata in X if abs(vtOrtho:getZ()) >= 0.707 then EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) else EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_BACK) end -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 1)) -- imposto offset radiale local dOffs = ( i - 1) * dStep EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- se possibile aumento l'affondamento pari al raggio corner + 1 if dMaxMat > (dDepth + dSawCornerRad + 1) then EgtSetMachiningParam( MCH_MP.DEPTH, (dDepth + dSawCornerRad + 1)) -- se massimo affondamento utensile inferiore fessura, setto affondamento ed emetto warning elseif dMaxMat < dDepth then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat) sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- eseguo if not EgtApplyMachining( true, false) then if EgtGetOutstrokeInfo() then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, GetChainSawBlockedAxis( 2)) if BD.C_SIMM then local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nLundIdFace, GDB_ID.ROOT) if vtN:getY() > 0 then EgtSetMachiningParam( MCH_MP.INITANGS, 'C=180') else EgtSetMachiningParam( MCH_MP.INITANGS, 'C=-180') end end if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end if EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end end end end -- altrimenti non è una fessura else -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- verifico se U local bIsU = ( Proc.Fct == 3 and not TestElleShape3( Proc)) -- verifico se due facce o L con una o due facce di terminazione local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2) -- se fattibile con fresa BH di fianco e spessore utensile inferiore alla larghezza faccia local bMakeBySideMill, bHead, bHeadDir, sMilling, dMaxMat, dToolDiam = VerifyIfByBHSideMill( Proc) if bMakeBySideMill and ( dMaxMat <= dV + 15 * GEO.EPS_SMALL) then -- se smusso non è esclusivo if nChamfer < 2 then -- recupero la larghezza della faccia perpendicolarmente alle altre 2 local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, EgtIf( nFacInd == 0, 1, 0), GDB_ID.ROOT) local vtX = vtN2 ^ vtN local frRef = Frame3d( ptC, ptC + 100 * vtX, ptC + 100 * vtN2) local b3Ref = EgtSurfTmGetFacetBBoxRef( Proc.Id, nFacInd, GDB_BB.STANDARD, frRef) if b3Ref then dV = b3Ref:getDimY() dH = b3Ref:getDimX() end -- se lavorazione da sotto e lunga, va divisa in due metà local bDouble = ( vtN:getZ() < -0.5 and dH > ( BD.MAX_LEN_BH_FROM_BOTTOM or 200)) -- inserisco la lavorazione di fresatura local sName = 'BHMill_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end sName = EgtGetName( nMchFId) -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd}}) -- imposto uso del lato faccia EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bHeadDir, MCH_MILL_FU.PARAL_LEFT, MCH_MILL_FU.PARAL_RIGHT)) -- calcolo step effettivo ed elevazione local dVcalc = dV - dMaxMat local dStep = EgtMdbGetCurrMachiningParam( MCH_MP.STEP) or dMaxMat local nStep = ceil( dVcalc / dStep) if vtN:getZ() < - 0.5 and ( nStep % 2) == 0 then nStep = nStep + 1 end dStep = dVcalc / nStep + 0.1 EgtSetMachiningParam( MCH_MP.STEP, dStep) -- imposto elevazione e dichiaro non si generano sfridi per VMill local sNotes = 'MaxElev=' .. EgtNumToString( dVcalc + dStep, 2) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- attacchi e uscite if vtN:getZ() > -0.5 then EgtSetMachiningParam( MCH_MP.LITANG, 0) EgtSetMachiningParam( MCH_MP.LIPERP, dFacElev + BD.CUT_SIC) else EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2 + BD.CUT_SIC) EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LO.LINEAR) EgtSetMachiningParam( MCH_MP.LOTANG, 0) EgtSetMachiningParam( MCH_MP.LOPERP, dFacElev + BD.COLL_SIC) if bDouble then EgtSetMachiningParam( MCH_MP.ENDADDLEN, - dH / 2) end end -- tipo passate multiple local nStepType = EgtIf( ( Proc.HeadDir and vtN:getY() < -0.5) or ( not Proc.HeadDir and vtN:getY() > 0.5), MCH_MILL_ST.ONEWAY, MCH_MILL_ST.ZIGZAG) EgtSetMachiningParam( MCH_MP.STEPTYPE, nStepType) -- imposto posizione braccio porta testa local nSCC = EgtIf( ( vtN:getY() > 0.5 or ( bHeadDir and vtN:getZ() > 0.5 ) or ( not bHeadDir and vtN:getZ() < -0.5)), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- se divisa in due metà if bDouble then local nMchFNId = EgtCopyMachining( sName .. '_2', sName) if not nMchFNId then local sErr = 'Error copying machining ' .. sName EgtOutLog( sErr) return false, sErr end -- inverto direzione e lato di lavoro e direzione ausiliaria local bInvert = EgtGetMachiningParam( MCH_MP.INVERT) EgtSetMachiningParam( MCH_MP.INVERT, not bInvert) local nWorkSide = EgtGetMachiningParam( MCH_MP.WORKSIDE) EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( nWorkSide == MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)) EgtSetMachiningParam( MCH_MP.SCC, EgtIf( nSCC == MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)) -- eseguo if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFNId, false) return false, sErr end end end -- altrimenti lavoro con svuotatura else local bSpecial3faces = false -- verifico se lavorando la faccia principale rimane esclusa molta sezione trasversale complessiva della feature (da box) local rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) local bBoxF = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, rfFac) if dH * dV < 0.9 * ( bBoxF:getDimX() * bBoxF:getDimY()) then bSpecial3faces = true end -- se riconosciuta gestione 3 facce -- e limitata per ora alla feature 20 if bSpecial3faces and Proc.Prc == 20 then -- se smusso non è esclusivo if nChamfer < 2 then -- entrambe le facce non devono essere orientate verso il basso local _, vtN2 = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) -- se orientata verso il basso, verifico l'alternativa if vtN:getZ() < BD.NZ_MINA and vtN2:getZ() < BD.NZ_MINA then local sErr = 'Error : special LapJoint from bottom impossible' EgtOutLog( sErr) return false, sErr end rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) rfFac2, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd2, GDB_ID.ROOT) -- eventuali tagli preliminari do local bOk, sErr = MakePreCuts( Proc, nPhase, nRawId, nPartId, dOvmHead, b3Raw, nChamfer) if not bOk then return false, sErr end end -- Recupero la lavorazione di fresa local sMilling = ML.FindMilling( 'LongSmallCut') if not sMilling then local sErr = 'Error : LongSmallCut not found in library' EgtOutLog( sErr) return false, sErr end -- Recupero la lavorazione di svuotatura local sMchFind = 'Pocket' -- se forzato uso truciolatore if EgtGetInfo( Proc.Id, Q_USE_ROUGH_TOOL, 'i') == 1 then sMchFind = 'OpenPocket' end local dDiam = min( dH, dV) local dDiam2 = min( dH2, dV2) local dCollSic = 2 * BD.COLL_SIC local dCollSic2 = 2 * BD.COLL_SIC if abs( vtN:getX()) > 0.7 or abs( vtN:getY()) > 0.7 or abs( vtN:getZ()) > 0.7 then dCollSic = 0 end if abs( vtN2:getX()) > 0.7 or abs( vtN2:getY()) > 0.7 or abs( vtN2:getZ()) > 0.7 then dCollSic2 = 0 end local sPocketing = ML.FindPocketing( sMchFind, dDiam2, dFacElev2 + dCollSic2) -- se non trova una svuotatura adatta provo ad assegnarla all'altra faccia if not sPocketing then dDiam, dDiam2 = dDiam2, dDiam dCollSic, dCollSic2 = dCollSic2, dCollSic nFacInd, nFacInd2 = nFacInd2, nFacInd dH, dH2 = dH2, dH dV, dV2 = dV2, dV dFacElev, dFacElev2 = dFacElev2, dFacElev rfFac, rfFac2 = rfFac2, rfFac vtN, vtN2 = vtN2, vtN sPocketing = ML.FindPocketing( sMchFind, dDiam2, dFacElev2 + dCollSic2) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr end end -- provo con contornatura local dDiamTool = 20 if bIsL then local bOk, sErr bOk, sWarn, dDiamTool = MakeByMill( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dFacElev, dCollSic, true, sMilling, nFacInd2, dFacElev2) if not bOk then return bOk, sWarn end else local sErr = 'Error : Impossible mill special LapJoint' EgtOutLog( sErr) return false, sErr end -- inserisco la lavorazione di svuotatura local sName = 'Pock_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) local nMchFId = EgtAddMachining( sName, sPocketing) if not nMchFId then local sErr = 'Error adding machining ' .. sName .. '-' .. sPocketing EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, nFacInd2}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT) -- imposto posizione braccio porta testa if vtN:getY() < GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YM) else EgtSetMachiningParam( MCH_MP.SCC, MCH_SCC.ADIR_YP) end -- se tasca aperta, imposto opportuno attacco if sMchFind == 'OpenPocket' then EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) end -- imposto elevazione local sNotes = 'MaxElev=' .. EgtNumToString( dFacElev2, 1) .. ';' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not EgtApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not EgtApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- se abilitato dal parametro Q inserisco foro sullo spigolo if EgtGetInfo( Proc.Id, Q_BORE_ON_CORNER, 'i') == 1 then local bOk bOk, sWarn = MakeDrillOnCorner( Proc, nPhase, nRawId, nPartId, b3Raw, 0, nAddGrpId, dDiamTool, true) if not bOk then return false, sWarn end -- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura elseif EgtGetInfo( Proc.Id, Q_BORE_ON_CORNER, 'i') == 2 then local bOk bOk, sWarn = MakeSharpCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, 0, nAddGrpId, dDiamTool) if not bOk then return false, sWarn end end end -- altrimenti lavorazione di svuotatura o contornatura else local bUseOtherFace -- se orientata verso il basso e non c'è testa da sotto, verifico l'alternativa if vtN:getZ() < BD.NZ_MINA and not BD.DOWN_HEAD and nFacInd2 then ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev bUseOtherFace = true end -- verifico non sia orientata verso il basso o ci sia una testa dal basso local bFaceDown = ( vtN:getZ() < BD.NZ_MINA) if bFaceDown and not BD.DOWN_HEAD then local sErr = 'Error : LapJoint from bottom impossible' EgtOutLog( sErr) return false, sErr end rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- se forma a L e la componente in X è maggiore di 60° allora verifico se posso utilizzare la faccia secondaria if bIsL and abs( vtN:getX()) > 0.866 then -- se non ho scambiato la faccia if not bUseOtherFace then if nFacInd2 then nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) -- altrimenti cerco la faccia secondaria per adiacenza alla principale else -- Cerco una faccia adiacente alla principale sul lato lungo local nFacAdj, sErr = GetFaceAdj( Proc, nFacInd, dH, dV) if nFacAdj < 0 then EgtOutLog( sErr) return false, sErr end nFacInd = nFacAdj dFacElev = BL.GetFaceElevation( Proc.Id, nFacInd) ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd, GDB_ID.ROOT) rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) end -- altrimenti se ho già cambiato faccia do errore per impossibilità di lavorazione else local sErr = 'Error : impossible to machine by side angle too big that cause collision' EgtOutLog( sErr) return false, sErr end end -- eventuali tagli preliminari do local bOk, sErr = MakePreCuts( Proc, nPhase, nRawId, nPartId, dOvmHead, b3Raw, nChamfer) if not bOk then return false, sErr end end -- imposto altezza aggiuntiva di elevazione local dCollSic = CalcCollisionSafety( vtN) -- abilitazione lavorazione da sotto local bMillUp = ( BD.DOWN_HEAD and vtN:getZ() > -0.259) local bMillDown = ( BD.DOWN_HEAD and vtN:getZ() < 0.342) -- settaggio voluto da Alessandro/Fabio (per fare angoli con fresa piccola) sMchFind = 'Pocket' local dDiam = min( dH, dV) if bSinglePart and (( Proc.Fct == 1) or ( Proc.Fct == 2 and bIsL) or ( Proc.Fct == 3 and bIsU)) then sMchFind = 'OpenPocket' if bIsU then dDiam = GetUShapeWidth( Proc, nFacInd) or dDiam else dDiam = 300 end end sMchFindBackUp = sMchFind local nUseRoughTool = EgtIf( bSinglePart, 0, 1) local nUseRT -- 04/08/2020 Se settato parametro uso truciolatore (parametro Q), non si devono prendere altre frese, si da errore (Fabio) -- Questa opzione si scontra facilmente con altre interpretazioni dello stasso parametro Q (per tornare indietro bNewCheck = false) local bNewCheck = true -- se processo 20 e non sto usando il truciolatore if bNewCheck and Proc.Prc == 20 and nUseRoughTool == 0 then -- verifico se forzato uso truciolatore nUseRT = EgtGetInfo( Proc.Id, Q_USE_ROUGH_TOOL, 'i') if nUseRT and nUseRT ~= 0 then sMchFind = 'OpenPocket' nUseRoughTool = 1 end end -- 03/12/2020 aggiunto controllo su feature 30 senza uso truciolatore if bNewCheck and Proc.Prc == 30 and nUseRoughTool == 0 then -- verifico se forzato uso truciolatore nUseRT = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') if nUseRT and nUseRT ~= 0 then sMchFind = 'OpenPocket' nUseRoughTool = 1 end end -- se processo 20 e non sto usando il truciolatore if Proc.Prc == 20 and nUseRoughTool == 0 then if nUseRT and nUseRT ~= 0 then sMchFind = 'OpenPocket' nUseRoughTool = 1 end end -- se da sotto, imposto massima lunghezza secondo la direzione local dMaxTotLen if bMillDown and BD.GetBottomToolMaxTotLen then dMaxTotLen = BD.GetBottomToolMaxTotLen( vtN) end -- ricerca lavorazione local sPocketing local sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, dFacElev + dCollSic, dMaxTotLen) if not sMyPocketing then sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind .. EgtIf( bMillDown, '_H2', ''), dDiam, nil, dMaxTotLen) end if not sMyPocketing and bMillUp then sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam, dFacElev + dCollSic) if not sMyPocketing then sMyPocketing, dMyTDiam, dMyTMaxDepth = ML.FindPocketing( sMchFind, dDiam) end bMillDown = false end if sMyPocketing and ( dMyTMaxDepth > 0.8 * dFacElev + dCollSic or ( bIsL and nUseRoughTool == 0)) then sPocketing = sMyPocketing end if bMillDown then sMchFind = sMchFind ..'_H2' end -- se feature 16 e forzata lama e forma ad U, annulla la svuotatura if Proc.Prc == 16 and bForceUseBlade and Proc.Fct == 3 and bIsU then sPocketing = nil end -- se non trova una svuotatura adatta if not sPocketing then -- se forma a L provo con contornatura if bIsL then -- se smusso non è esclusivo if nChamfer < 2 then return MakeByMill( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dFacElev, dCollSic) end -- altrimenti, in base alla forma, provo con svuotature di fianco o con la sega a catena o lama else local bTryWithBlades = true local nOk, bOk, sStat, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFaces -- se feature 16 o 17 e se forzata lama provo prima con questa e poi con la fresa if ( Proc.Prc == 16 or Proc.Prc == 17) and bForceUseBlade then -- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame if bTryWithBlades and nChamfer < 2 then -- anche su macchine con testa da sotto, la sega a catena è solo da sopra if vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and nFacInd2 then ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev bUseOtherFace = true rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) end -- eseguo bOk, sWarn, sStat = MakeByChainOrSaw( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dFacElev, bForceUseBlade, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFaces, nBottomFace, nChamfer, nAddGrpId, b3Solid, dDepthCham, true) if not bOk then -- in base al flag interno e al numero di facce e se ha forma ad U: provo prima la svuotatura sul fianco e -- se non è possibile allora provo in seguito con lama o segacatena -- o passare subito dalla lavorazione con lama/sega catena if Proc.Fct == 3 and bIsU then -- lavoro con svuotature (singola o doppia contrapposta) local sMyMchFind = 'Pocket' nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, _, _, _, _, _, bOrthoFaces = MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMyMchFind, true, b3Solid) -- se lavorazione non idonee ( asse della feature troppo inclinato e impossibile lavorare completamente da due parti) if nOk == -2 then if not sMchFind then sMchFind = sMchFindBackUp end sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr end elseif nOk < 0 then return false, sErr elseif nOk == 0 then if sStat == 'MNF' then sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr end else return bOk, sWarn end else bOk = true return bOk, sErr end else sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr) return false, sErr end end else return bOk, sWarn end else -- se devo inserire il chamfer if ( ( Proc.Fct == 3 and bIsU) or (Proc.Fct == 2 and bIsL)) and nChamfer > 0 then -- ottengo le dimensioni dello pseudotunnel local _, _, _, vtOrtho, _, nSurfInt = GetTunnelDimension( Proc, nPartId) local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham) if nOk < 0 then return false, sErr end end bOk = true return bOk, sWarn end else -- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo -- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa -- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z local bMadeASbyBld = false local bPassThrou = ( Proc.Box:getDimY() > b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > b3Raw:getDimZ() - 1) if nChamfer < 2 and EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') == 1 and (( bIsU or bIsL) and bPassThrou) then local bOk bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, b3Raw, bIsU, vtN, nFacet, nFacInd, sWarn, true) if not bOk then return false, sWarn end end -- in base al flag interno e al numero di facce e se ha forma ad U: provo prima la svuotatura sul fianco e -- se non è possibile allora provo in seguito con lama o segacatena -- o passare subito dalla lavorazione con lama/sega catena if bTrySidePocketAtFirst and Proc.Fct == 3 and bIsU then -- lavoro con svuotature (singola o doppia contrapposta) local sMyMchFind = 'Pocket' local dDiamTool = 100 local nPathInt, nSurfInt, bOneShot nOk, sErr, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, dDiamTool, bDoubleSide, nPathInt, nSurfInt, bOneShot, bOrthoFaces = MakeByPockets( Proc, nPhase, nRawId, nPartId, nChamfer, dDepthCham, nAddGrpId, sMyMchFind, true, b3Solid) if nOk == -2 then if not sMchFind then sMchFind = sMchFindBackUp end sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr2 = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr2) return false, sErr2 end bTryWithBlades = false sWarn = sErr elseif nOk < 0 then return false, sErr elseif nOk > 0 then bTryWithBlades = false sWarn = sErr -- se ho antischeggia con fori le inserisco -- if nChamfer < 2 and EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') == 2 and (( bIsU or bIsL) and bPassThrou) then -- local bOk -- bMadeASbyBld, bOk, sWarn = ManageAntiSplintByDrill( Proc, b3Raw, bIsU, vtOrtho, vtN, nFacet, nFacInd, sWarn) -- if not bOk then return false, sWarn end -- end -- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola local nContourSmallTool = EgtGetInfo( Proc.Id, Q_CONTOUR_SMALL_TOOL, 'i') or 0 if nContourSmallTool > 0 then local bOk, sWarn2 bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiamTool, nContourSmallTool, bDoubleSide, vtOrtho, nPathInt, nSurfInt, b3Solid, dDepth, bOneShot) if not bOk then return false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end end end bOk = true end -- 03/09/2020 da conferma di Fabio Squaratti: Per ora solo sulla feature 016: -- se ha fallito la fresatura (qua sopra) allora di defalut ( anche se il flag Q della lama è disattivato) prima provo la lama if Proc.Prc == 16 then bForceUseBlade = true end -- Se la svuotatura precedente non è stata fatta e smusso non è esclusivo, provo con le lame if bTryWithBlades and nChamfer < 2 then -- anche su macchine con testa da sotto, la sega a catena è solo da sopra if vtN:getZ() < BD.NZ_MINA and BD.DOWN_HEAD and nFacInd2 then ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFacInd2, GDB_ID.ROOT) nFacInd, nFacInd2 = nFacInd2, nFacInd dFacElev, dFacElev2 = dFacElev2, dFacElev bUseOtherFace = true rfFac, dH, dV = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nFacInd, GDB_ID.ROOT) end -- eseguo bOk, sWarn, sStat = MakeByChainOrSaw( Proc, nPhase, nRawId, nPartId, nFacInd, rfFac, dH, dV, dFacElev, bForceUseBlade, dDimMin, dDimMax, dDepth, vtOrtho, nLundIdFace, bOrthoFaces, nBottomFace, nChamfer, nAddGrpId, b3Solid, dDepthCham) if not bOk and sStat == 'MNF' then sPocketing = ML.FindPocketing( sMchFind, dDiam) if not sPocketing then local sErr2 = 'Error : '..sMchFind..' not found in library' EgtOutLog( sErr2) return false, sErr2 end else -- se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola local nContourSmallTool = EgtGetInfo( Proc.Id, Q_CONTOUR_SMALL_TOOL, 'i') or 0 if nContourSmallTool > 0 then local bOk, sWarn2 bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, 100, nContourSmallTool) if not bOk then return false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end end return bOk, sWarn end -- altrimenti verifico se ho già svuotato dal fianco, se si esco else -- se non ho annullato la/le svuotatura/e dal fianco if nOk ~= -2 then return bOk, sWarn end end end end else -- se devo inserire il chamfer if ( ( Proc.Fct == 3 and bIsU) or (Proc.Fct == 2 and bIsL)) and nChamfer > 0 then -- ottengo le dimensioni dello pseudotunnel local _, _, _, vtOrtho, _, nSurfInt = GetTunnelDimension( Proc, nPartId) local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham) if nOk < 0 then return false, sErr end end end -- se richiesti antischeggia con lama su U trasversale e smusso non esclusivo -- rimane da gestire: se da eseguire con fresa o se richiesto lama ma impossibile utilizzarla, si utilizza fresa -- 2021.04.27 esegue antischeggia di lama se forma U o L con feature passante in Y o Z local bMadeASbyBld = false local bPassThrou = ( Proc.Box:getDimY() > b3Raw:getDimY() - 1 or Proc.Box:getDimZ() > b3Raw:getDimZ() - 1) if nChamfer < 2 and EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') == 1 and (( bIsU or bIsL) and bPassThrou) then local bOk bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, b3Raw, bIsU, vtN, nFacet, nFacInd, sWarn) if not bOk then return false, sWarn end end -- se smusso non esclusivo if nChamfer < 2 then -- eseguo la svuotatura della faccia principale, mi restituisce id utensile, il diametro utensile per il foro opzionale local tvtNx = {} tvtNx[2] = vtN local bOk, sWarn2 bOk, sWarn2, sTuuidPk, dDiamTool = MakePocket( Proc, nPartId, ptC, tvtNx, nFacInd, sMchFind, nUseRoughTool, sPocketing, dFacElev + dCollSic) if not bOk then return false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end -- se ho più di 3 facce e non di forma ad u oppure ho 3 facce e di forma ad u -- e non sono stati inseriti antischeggia di lama -- controllo se c'è una faccia non ortogonale alla principale e la lavoro con una contornatura o svuotatura if ( ( Proc.Fct > 3 and not bIsU) or ( Proc.Fct == 3 and bIsU)) and not bMadeASbyBld then -- Recupero le facce adiacenti alla principale local vAdj = EgtSurfTmFacetAdjacencies( Proc.Id, nFacInd)[1] if not vAdj or #vAdj == 0 then local sErr = 'Error : main face without adjacencies' EgtOutLog( sErr) return false, sErr end -- Cerco una faccia adiacente alla principale con angolo > 90 local nFacAdj local tDimAndRef = {} tvtNx = {} tvtNx[1] = vtN tDimAndRef[1] = {dH, dV, rfFac} for i = 1, #vAdj do if vAdj[i] >= 0 then local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, vAdj[i], GDB_ID.ROOT) if bAdj and dAng < 0 and 180 + dAng > 90.1 then local rfFac2, dH2, dV2 = EgtSurfTmFacetMinAreaRectangle( Proc.Id, vAdj[i], GDB_ID.ROOT) _, tvtNx[2] = EgtSurfTmFacetCenter( Proc.Id, vAdj[i], GDB_ID.ROOT) tDimAndRef[2] = {dH2, dV2, rfFac2} local ptPs = ( ptP1 + ptP2) / 2 local bOk, sWarn2 bOk, sWarn2 = MachineByMill( Proc, nPhase, nRawId, nPartId, b3Solid, tvtNx, nFacInd, vAdj[i], ptPs, tDimAndRef, b3Raw, EgtIf( ( Proc.Fct == 3 and bIsU), 0, 2), nUseRoughTool, dAng, sPocketing, sTuuidPk, dFacElev) if not bOk then return bOk, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end end end end end local nBoreOnCorner = EgtGetInfo( Proc.Id, Q_BORE_ON_CORNER, 'i') or 0 local nContourSmallTool = EgtGetInfo( Proc.Id, Q_CONTOUR_SMALL_TOOL, 'i') or 0 -- se abilitato dal parametro Q inserisco foro sullo spigolo if nBoreOnCorner == 1 then local bOk, sWarn2 bOk, sWarn2 = MakeDrillOnCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiamTool) if not bOk then return false, sWarn2 end sWarn = sWarn .. '\n' .. sWarn2 if sWarn2 then if not sWarn then sWarn = '' end sWarn = sWarn .. '\n' .. sWarn2 sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end -- altrimenti se abilitato dal parametro Q inserisco percorso di pulitura elseif nBoreOnCorner == 2 then local bOk, sWarn2 bOk, sWarn2 = MakeSharpCleanCorner( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiamTool) if not bOk then return false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end -- altrimenti se abilitato dal parametro Q inserisco pulitura spigoli o contorno con fresa più piccola elseif nContourSmallTool > 0 then local bOk, sWarn2 bOk, sWarn2 = MakeRoundCleanCornerOrContour( Proc, nPhase, nRawId, nPartId, b3Raw, nFacInd, nAddGrpId, dDiamTool, nContourSmallTool) if not bOk then return false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end end end end end end return true, sWarn end --------------------------------------------------------------------- local function MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead) -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) -- la divido in parti lungo X local vAddId = {} local nPart = max( ceil( Proc.Box:getDimX() / BD.LONGCUT_MAXLEN), 2) local dPartLen = Proc.Box:getDimX() / nPart local Xmin = Proc.Box:getMin():getX() for i = 1, nPart do -- eseguo divisione local AddId = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL EgtSetName( AddId, 'AddPart_' .. tostring( Proc.Id) .. '_' .. tostring( i)) if i > 1 then local ptOn = Point3d( Xmin + ( i - 1) * dPartLen, 0, 0) EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB) end if i < nPart then local ptOn = Point3d( Xmin + i * dPartLen, 0, 0) EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB) end table.insert( vAddId, AddId) end -- applico le lavorazioni sulle diverse parti local sWarn for i = 1, #vAddId do local b3Box = EgtGetBBoxGlob( vAddId[i], GDB_BB.STANDARD) local nFct = EgtSurfTmFacetCount( vAddId[i]) local AddProc = { Id = vAddId[i], Grp = Proc.Grp, Prc = Proc.Prc, Box = b3Box, Fct = nFct, Flg = Proc.Flg} local bOk, sMyWarn = MakeMoreFaces( AddProc, nPhase, nRawId, nPartId, dOvmHead, false) if not sWarn then sWarn = sMyWarn end if not bOk then return bOk, sWarn end end return true, sWarn end --------------------------------------------------------------------- -- Applicazione della lavorazione --------------------------------------------------------------------- function ProcessLapJoint.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) -- setto a nil la variabile smussi bMadeChamfer = nil -- limiti di fresatura semplice local MAX_MILL_LIN = 80 -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) -- in base al tipo di feature attribuisco il significato dei parametri Q AssignQIdent( Proc) -- se non forzate frese, uso la lama local bUseBlade = EgtGetInfo( Proc.Id, Q_USE_ROUGH_TOOL, 'i') ~= 1 and EgtGetInfo( Proc.Id, Q_USE_MILL, 'i') ~= 1 -- se ho attivo la lama e ho la feature 30, verifico i parametri Q propri della feature if bUseBlade then if Proc.Prc == 30 then local nBladeAntisplint = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') or 0 local nUseRoughToolOnSide = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0 -- se antischeggia di fresa o abilitato sgrossatore di fianco if nBladeAntisplint == 2 or nUseRoughToolOnSide == 1 then bUseBlade = false end -- se ho attivo la lama e ho la feature 32, verifico i parametri Q propri della feature elseif Proc.Prc == 32 then local nBladeAntisplint = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') or 0 local nUseRoughToolOnSide = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0 -- se antischeggia di fresa o abilitato sgrossatore di fianco if nBladeAntisplint == 2 or nUseRoughToolOnSide == 1 then bUseBlade = false end -- se ho attivo la lama e ho la feature 34, verifico i parametri Q propri della feature elseif Proc.Prc == 34 then local nBladeAntisplint = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') or 0 -- se antischeggia di fresa o abilitato sgrossatore di fianco if nBladeAntisplint == 2 then bUseBlade = false end end end -- se lunghezza richiede spezzatura if Proc.Box:getDimX() > BD.LONGCUT_MAXLEN then -- una faccia if Proc.Fct == 1 then return LongCut.Make( Proc, nPhase, nRawId, nPartId) -- due facce elseif Proc.Fct == 2 then -- determino se due facce lunghe oppure una lunga e l'altra terminale local b3Fac1 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 0, GDB_BB.STANDARD) local b3Fac2 = EgtSurfTmGetFacetBBoxGlob( Proc.Id, 1, GDB_BB.STANDARD) if abs( b3Fac1:getDimX() - b3Fac2:getDimX()) < 50 then -- leggo i parametri Q per utilizzare la fresa di fianco e/o lama local nUseSideTool = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0 local bUseBlade = EgtGetInfo( Proc.Id, Q_ANTISPLINT_TYPE, 'i') == 1 return Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool) elseif b3Fac1:getDimX() < 1 then -- la faccia 0 deve essere quella lunga EgtSurfTmSwapFacets( Proc.Id, 0, 1) if bUseBlade then return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide') else return LongCut.Make( Proc, nPhase, nRawId, nPartId) end elseif b3Fac2:getDimX() < 1 then if bUseBlade then return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide') else return LongCut.Make( Proc, nPhase, nRawId, nPartId) end else if bUseBlade then return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide') else return MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead) end end -- tre o più facce else return MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead) end -- altrimenti lavorazione unica else -- una faccia if Proc.Fct == 1 then -- se piccola, con fresa if not bUseBlade and ( Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN)) then return MakeOneFaceByMill( Proc, nPhase, nRawId, nPartId) -- altrimenti, con lama else return Cut.Make( Proc, nPhase, nRawId, nPartId, dOvmHead) end -- due facce elseif Proc.Fct == 2 then -- recupero l'ingombro della trave local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) if not b3Solid then local sErr = 'Error : part box not found' EgtOutLog( sErr) return false, sErr end -- se praticamente è lunga come la trave if Proc.Box:getDimX() > 0.8 * b3Solid:getDimX() then local nUseSideTool = EgtGetInfo( Proc.Id, Q_SIDE_ROUGH_TOOL, 'i') or 0 return Long2Cut.Make( Proc, nPhase, nRawId, nPartId, bUseBlade, nUseSideTool) -- altrimenti else -- verifico se da lavorare con testa da sotto local bDownHead = false if BD.DOWN_HEAD then local ptC = {} local vtN = {} ptC[1], vtN[1] = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) ptC[2], vtN[2] = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) local vtNm = ( vtN[1] + vtN[2]) ; vtNm:normalize() bDownHead = ( vtNm:getZ() < -0.5) end -- determino l'angolo tra le facce local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) -- se ortogonali e non forzata lama oppure con testa da sotto, con fresa if ( not bUseBlade or bDownHead) and bAdj and abs( dAng + 90) < 1 then -- se piccole if Proc.Box:getDimX() < MAX_MILL_LIN and ( Proc.Box:getDimZ() < MAX_MILL_LIN or Proc.Box:getDimY() < MAX_MILL_LIN) then return MakeTwoFacesByMill( Proc, nPhase, nRawId, nPartId, bDownHead) else return MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, true) end -- altrimenti, con lama else -- verifico se devo fare prima gli smussi -- recupero gruppo per geometria addizionale local nAddGrpId = BL.GetAddGroup( nPartId) if not nAddGrpId then local sErr = 'Error : missing AddGroup' EgtOutLog( sErr) return false, sErr end -- verifico se due facce o L con una o due facce di terminazione local bIsL = ( Proc.Fct == 2 or TestElleShape3( Proc) or TestElleShape4( Proc) == 2) -- verifico se sono presenti i parametri Q per la profondità smusso e -- per eseguire in esclusiva solo lo smusso local nChamfer, dDepthCham, sErrCham = EvaluateQParam( Proc) if Proc.Fct == 2 and bIsL and nChamfer > 0 then local _, _, _, vtOrtho, _, nSurfInt = GetTunnelDimension( Proc, nPartId) local nOk, sErr = MakeChamfer( Proc, true, nAddGrpId, vtOrtho, b3Solid, nSurfInt, dDepthCham) if nOk < 0 then return false, sErr end end return Fbs.MakeTwo( Proc, nPhase, nRawId, nPartId, dOvmHead, 'HeadSide' .. EgtIf( bDownHead, '_H2', ''), true, bDownHead) end end -- tre o più facce else return MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, true) end end end --------------------------------------------------------------------- return ProcessLapJoint