-- ProcessLongDoubleCut.lua by Egaltech s.r.l. 2023/06/07 -- Gestione calcolo doppio taglio longitudinale per Travi -- 2021/05/18 Possibile taglio con lama anche di fianco su macchina con testa da sotto. -- 2021/06/29 Corretta gestione caso equivalente a due smussi. -- 2021/10/29 Aggiunta opzione tipo lavorazione 'LongCut'. -- 2021/11/08 Se con lama e flag BD.USE_LONGCUT si lavora in direzione contraria allo standard. -- 2022/02/08 Sistemate lunghezze fresature quando due sole. -- 2022/02/15 Sistemati commenti. -- 2022/03/20 Tolta da scelta milling tipo Long2CutDown controllo max diametro fresa. -- 2022/05/27 Corretto ordine per casi sui lati. -- 2022/06/29 Corretto calcolo lunghezza attacco/uscita perpendicolare per lavorazioni di fianco. -- 2022/11/30 Modifiche su SCC per TURN. -- 2023/01/26 Rimossa la pulitura della faccia laterale nel caso in cui la feature abbia almeno una faccia rivolta verso il basso. -- 2023/01/27 In MakeSideFace il prolungamento di uscita è ora fissato a 10 mm. -- 2023/02/15 Migliorato verso di avanzamento della lama. -- 2023/02/21 Verso di avanzamento della lama migliorato anche con lama LC. -- 2023/02/22 Nuova gestione del verso di avanzamento ottimale che contempla tutti i casi. -- 2023/03/06 Correzione per i casi con lavorazione limitata. -- 2023/03/23 Correzione per caso con doppia lama da sotto. -- 2023/06/07 Sistemazione SCC per macchina TURN -- 2023/10/24 Migliorata spezzatura taglio passante con due spezzoni -- 2023/10/25 Se effettivamente un taglio longitudinale e lama non taglia completamente, limito la lavorazione. Altrimenti esco. -- 2023/11/24 Aggiunta Q05 per utilizzo lama anche in feature cieche conme per LongCut. -- 2023/11/30 Calcolo elevazione velocizzato e centralizzato tramite la funzione GetFaceElevation. -- 2024/01/18 Implementata GetBlockedAxis che gestisce gli assi bloccati per tutti i tipi di utensile. -- 2024/03/21 Corretto parametro passato a funzione BL.GetBlockedAxis. Ora tiene in considerazione anche testa sotto -- Tabella per definizione modulo local ProcessLong2Cut = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') EgtOutLog( ' ProcessLongDoubleCut started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') local Topology = require( 'FeatureTopology') local dLimMinPiece = BD.LEN_SHORT_PART or 1000 --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessLong2Cut.Identify( Proc) return ( Proc.Grp == 0 and Proc.Prc == 12) end --------------------------------------------------------------------- -- Identificazione delle facce della feature. -- Ritorna quattro valori : -- flag delle facce limitanti (0= no, 1= a destra, 2= a sinistra, 3= entrambe) -- vettore indici facce longitudinali -- vettore dei centri delle facce longitudinali -- vettore dei centri delle normali local function IdentifyFaces( Proc) local nFaceLimit = 0 local tFaceLong = {} local tptC = {} local tvtN = {} -- verifico le normali delle facce local nFacetCnt = EgtSurfTmFacetCount( Proc.Id) for i = 1, nFacetCnt do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT) -- se è una faccia limite a sinistra if vtN:getX() > GEO.EPS_SMALL then nFaceLimit = nFaceLimit | 2 -- se è una faccia limite a destra elseif vtN:getX() < -GEO.EPS_SMALL then nFaceLimit = nFaceLimit | 1 -- altrimenti è una faccia longitudinale else local nInd = #tFaceLong + 1 tFaceLong[nInd] = i-1 tptC[nInd], tvtN[nInd] = EgtSurfTmFacetCenter( Proc.Id, ( i-1), GDB_ID.ROOT) end end return nFaceLimit, tFaceLong, tptC, tvtN end --------------------------------------------------------------------- -- Classificazione della feature function ProcessLong2Cut.Classify( Proc) local nUseMillOnSide = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0 -- se richiesto utensile di fianco if nUseMillOnSide > 0 then -- carico i dati delle face già inserite nelle opportune tabelle local nFaceLimit, tFaceLong, _, vtN = IdentifyFaces( Proc) -- verifico posizione (+1=sopra, -1=sotto, 0=sui lati) local nSide = 0 if vtN[1]:getZ() > -10 * GEO.EPS_SMALL and vtN[2]:getZ() > -10 * GEO.EPS_SMALL then nSide = 1 elseif vtN[1]:getZ() < 10 * GEO.EPS_SMALL and vtN[2]:getZ() < 10 * GEO.EPS_SMALL then nSide = -1 end -- angolo diedro per stabilire se taglio convesso local bAdj, _, _, dAng = EgtSurfTmFacetsContact( Proc.Id, tFaceLong[1], tFaceLong[2], GDB_ID.ROOT) local bConvex if bAdj then bConvex = ( dAng >= 0) else bConvex = true end -- se feature di fianco e facce concave per lavorazione impossibile -- if nSide == 0 and not bConvex then -- -- do errore perchè su un lato entra nel pezzo (entra nel lato sopra) -- Proc.ErrMsg = 'Error : impossible to machinine with tool on side' -- return false, false -- end end return true, false end --------------------------------------------------------------------- function ProcessLong2Cut.GetLongFacesCount( Proc) local nLongFaces = 0 local nFacetCnt = EgtSurfTmFacetCount( Proc.Id) for i = 1, nFacetCnt do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i-1, GDB_ID.ROOT) if abs( vtN:getX()) < GEO.EPS_SMALL then nLongFaces = nLongFaces + 1 end end return nLongFaces end --------------------------------------------------------------------- local function MakeSideFace( nId, nFac, nSideLimitingFace, nInd, sMilling, dToolDiam, nL2CSide, bIsAnyFaceUpsideDown) if ( not BD.DOWN_HEAD and not BD.TURN) and bIsAnyFaceUpsideDown then EgtOutLog( 'Long2Cut : side face finishing skipped, down head required') return true end -- inserisco la lavorazione local sNameF = 'L2C_' .. ( EgtGetName( nId) or tostring( nId)) .. '_' .. tostring( nFac) local nMchFId = EgtAddMachining( sNameF, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ nId, nFac}}) -- lato di lavoro e inversione if BD.TURN and ( ( nSideLimitingFace == 1 and nInd == EgtIf( nL2CSide ~= -1, 2, 1)) or ( nSideLimitingFace == -1 and nInd == EgtIf( nL2CSide ~= -1, 1, 2))) then EgtSetMachiningParam( MCH_MP.INVERT, true) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) else EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) end -- uso della faccia local nFaceUse = EgtIf( nSideLimitingFace == 1, MCH_MILL_FU.ORTHO_RIGHT, MCH_MILL_FU.ORTHO_LEFT) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- annullo offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, 0) -- attacco e uscita EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2 + 30) EgtSetMachiningParam( MCH_MP.LOPERP, 5) EgtSetMachiningParam( MCH_MP.LOTANG, 10) if BD.TURN then EgtSetMachiningParam( MCH_MP.LOELEV, 10) end -- se faccia di fianco e testa da sotto, aumento la sicurezza if nL2CSide == 0 and BD.DOWN_HEAD then EgtSetMachiningParam( MCH_MP.STARTPOS, 80) end -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end --------------------------------------------------------------------- -- Applicazione della lavorazione local function MakeByPocketing( Proc, nPhase, nRawId, nPartId, nSide, nFacInd, dFacElev) -- cerco la svuotatura opportuna local bDownHead = nSide ~=1 and BD.DOWN_HEAD local sPockType = EgtIf( bDownHead, 'OpenPocket_H2', 'OpenPocket') local sPocketing = ML.FindPocketing( sPockType, Proc.Box:getDimX(), nil, nil, not bDownHead, bDownHead) if not sPocketing then local sErr = 'Error : OpenPocket not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dMaxDepth = 0 if EgtMdbSetCurrMachining( sPocketing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMaxDepth = ( EgtTdbGetCurrToolMaxDepth() or dMaxDepth) end end -- inserisco la lavorazione 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, nFacInd}}) -- imposto uso faccia EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.ORTHO_CONT) -- imposto attacco per tasca aperta EgtSetMachiningParam( MCH_MP.SUBTYPE, MCH_POCK_SUB.SPIRALIN) -- se elevazione superiore a massimo affondamento della fresa, riduco opportunamente local sWarn if dFacElev > dMaxDepth + 10 * GEO.EPS_SMALL then EgtSetMachiningParam( MCH_MP.DEPTH, dMaxDepth - dFacElev) dFacElev = dMaxDepth sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end -- imposto elevazione e dichiaro non si generano sfridi per VMill local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) or '' sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', EgtNumToString( dFacElev, 1)) sUserNotes = EgtSetValInNotes( sUserNotes, 'VMRS', 0) EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) -- eseguo if not ML.ApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true, sWarn end --------------------------------------------------------------------- local function CalcBladeUse( bUseBlade, bDown_Head, nSide, vtN1, vtN2, bConvex, nOrd, bFront, dCustomAngle) local bCanUseBlade = false local bCanUseUnderBlade = false -- se lama abilitata e faccia da sopra if bUseBlade and nSide == 1 then bCanUseBlade = true end -- se lama abilitata e non c'è testa da sotto if bUseBlade and not bDown_Head then if nSide >= 0 then if nSide > 0 and ( ( vtN1 and vtN1:getZ() >= -0.0175) or ( vtN2 and vtN2:getZ() >= -0.0175)) then bCanUseBlade = true elseif nSide == 0 then if ( ( vtN1 and vtN1:getZ() >= -0.0175) or ( vtN2 and vtN2:getZ() >= -0.0175)) then bCanUseBlade = true elseif not bConvex and nOrd and (( nOrd == 1 and bFront) or ( nOrd == 2 and not bFront)) and ( vtN1 and vtN1:getZ() >= -0.0175) then bCanUseBlade = true elseif not bConvex and nOrd and (( nOrd == 2 and bFront) or ( nOrd == 1 and not bFront)) and ( vtN1 and vtN1:getZ() >= -0.5) then bCanUseBlade = true elseif bConvex and ( vtN1 and vtN1:getZ() >= -0.0175) then bCanUseBlade = true end end else if bConvex then if vtN1 and vtN2 then if vtN1:getZ() >= -0.5 then if vtN2:getZ() >= -0.5 then bCanUseBlade = true end else if vtN2:getZ() >= -0.0175 then bCanUseBlade = true end end else if ( vtN1 and vtN1:getZ() >= EgtIf( dCustomAngle, dCustomAngle, -0.5)) then bCanUseBlade = true end end else --if ( vtN1 and vtN1:getZ() >= EgtIf( dCustomAngle, dCustomAngle, -0.5)) and ( not vtN2 or vtN2:getZ() >= -0.5) then -- bCanUseBlade = true --end -- viene abilitata sempre lama da sotto bCanUseBlade = true end end end -- se lama abilitata e c'è testa da sotto if bUseBlade and bDown_Head then -- se faccia da sotto o di lato ma con versore Z negativo che supera i 30° da Z- if nSide <= 0 and ( ( vtN1 and vtN1:getZ() <= -0.5) or ( vtN2 and vtN2:getZ() <= -0.5)) then bCanUseUnderBlade = true end -- se faccia da sotto o di lato ma con versore Z negativo abilito la lavorazione con lame mixate if nSide <= 0 and ( ( vtN1 and vtN1:getZ() <= -0.0175) or ( vtN2 and vtN2:getZ() <= -0.0175)) then bCanUseUnderBlade = true end -- se faccia da sopra o di lato ma con versore Z negativo verifico che abbia un angolo compatibile per non avere extracorsa if nSide >= 0 and ( ( vtN1 and vtN1:getZ() > -0.4695) or ( vtN2 and vtN2:getZ() > -0.4695)) then bCanUseBlade = true end -- se faccia da sotto ma con versore Z negativo verifico che abbia un angolo compatibile per non avere extracorsa if nSide < 0 and ( ( vtN1 and vtN1:getZ() > -0.4695) or ( vtN2 and vtN2:getZ() > -0.4695)) then bCanUseBlade = true end end return bCanUseBlade, bCanUseUnderBlade end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessLong2Cut.Make( Proc, nPhase, nRawId, nPartId, bForcedBladeMaster, nUseSideToolMaster, nUseConventionalMilling) -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- carico i dati delle face già inserite nelle opportune tabelle local nFaceLimit, tFaceLong, ptC, vtN = IdentifyFaces( Proc) local dLen = Proc.Box:getDimX() -- inizializzazione tabella con eventuali lavorazioni create a posteriori da ritornare al chiamante local AddedIds = {} -- recupero lunghezza grezzo totale da info sulla macchinata local dBarLen = EgtGetInfo( EgtGetCurrMachGroup(), 'BARLEN', 'd') local dOvmHead = b3Raw:getMax():getX() - b3Solid:getMax():getX() -- verifico posizione (+1=sopra, -1=sotto, 0=sui lati) local nSide = 0 if vtN[1]:getZ() > 0.0175 and vtN[2]:getZ() > 0.0175 then nSide = 1 elseif vtN[1]:getZ() < -0.0175 and vtN[2]:getZ() < -0.0175 then nSide = -1 end local bIsAnyFaceUpsideDown = vtN[1]:getZ() < -0.0175 or vtN[2]:getZ() < -0.0175 -- angolo diedro per stabilire se taglio convesso local bInt, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, tFaceLong[1], tFaceLong[2], GDB_ID.ROOT) local bConvex local bOrtho local ptM local ptRef = ( ptC[1] + ptC[2]) / 2 if bInt then bConvex = ( dAng >= 0) bOrtho = ( abs( dAng + 90) < 1) ptM = ( ptP1 + ptP2) / 2 else ptM = ptRef local vtM1 = ptC[1] - ptM ; vtM1:normalize() local vtM2 = ptC[2] - ptM ; vtM2:normalize() bConvex = ( vtM1 * vtN[1] > 0 and vtM2 * vtN[2] > 0) bOrtho = false dAng = acos( vtN[1] * vtN[2]) -- se facce contrapposte e quindi concavo, angolo sempre negativo if not bConvex and dAng > 0 then dAng = -dAng end end -- ottengo la distanza tra la fine del pezzo e il pezzo successivo local dDistToNextPiece = BL.GetDistanceToNextPart( nRawId, nPhase) local bForcedLim local sWarn ---------------------------------------------------------------------------------------------------------------------------------------- -- 2020/09/17 Fabio Squaratti: se sono attivi entrambe i Q01 (lavorare con lama) e Q03 (lavorare con fresa di fianco anche da sopra) -- allora vince il Q3, cioè si utilizza la fresa di fianco ( per i tagli da sopra) -- 2020/09/17 Fabio Squaratti: se lavorazione con fresa di fianco e se ci sono delle facce laterali, l'utensile deve arrivare -- fino al punto più vicino della faccia laterale (prima l'arretramento era sempre del raggio utensile). -- Questo viene fatto se Q03=1 o fresa da sotto ---------------------------------------------------------------------------------------------------------------------------------------- local bUseBlade local nUseMillOnSide local bForceUseBladeOnNotThruFace -- se presenti utilizzo i parametri dell'eventuale lua "padre" if bForcedBladeMaster ~= nil then bUseBlade = bForcedBladeMaster else local nUseBlade = EgtGetInfo( Proc.Id, 'Q05', 'i') -- funzionamento Q05 -- -- 0: fresa; 1: lama solo se feature passante, faccia verso l'alto; 2: lama solo se feature passante, qualunque orientamento faccia; 3: lama con feature sia cieca che passante, faccia verso l'alto, lavorazione non rovina pezzo successivo; 4: lama con feature sia cieca che passante, qualunque orientamento faccia, lavorazione non rovina pezzo successivo -- feature passante if nFaceLimit == 0 then if nUseBlade == 2 or nUseBlade == 4 or ( nSide == 1 and ( nUseBlade == 1 or nUseBlade == 3)) then bUseBlade = true end -- feature cieca else if nUseBlade == 4 or ( nSide == 1 and ( nUseBlade == 3)) then bUseBlade = true bForceUseBladeOnNotThruFace = true end end end if nUseSideToolMaster ~= nil then nUseMillOnSide = nUseSideToolMaster else nUseMillOnSide = EgtGetInfo( Proc.Id, 'Q03', 'i') or 0 end -- se entrambe i Q sono attivi, disabilito lama if nUseMillOnSide > 0 then bUseBlade = false end -- verifico se posso usare lame local bCanUseBlade, bCanUseUnderBlade = CalcBladeUse( bUseBlade, BD.DOWN_HEAD, nSide, vtN[1], vtN[2], bConvex) -- introduco messaggi di errore in caso sia settata la lama ma impossibile utilizzarla -- se si toglie questa parte il processo continua utilizzando però la fresa ma per il vincolo del parametro Q non è possibile if bUseBlade and not BD.DOWN_HEAD and not bCanUseBlade then local sErr = 'Error, impossible use blade on too negative face' EgtOutLog( sErr) return false, sErr elseif bUseBlade and BD.DOWN_HEAD and not bCanUseBlade and not bCanUseUnderBlade then local sErr = 'Error, impossible use blade' EgtOutLog( sErr) return false, sErr end -- analisi del taglio local vOrd = {} local vFaceUse = {} local bIsMachDownUp = false if nSide == 1 or ( nSide == -1 and ( BD.DOWN_HEAD or BD.TURN)) then vOrd = EgtIf( ptC[1]:getY() < ptRef:getY(), { 1, 2}, { 2, 1}) vFaceUse = { BL.GetNearestOrthoOpposite( ptC[1] - ptM), BL.GetNearestOrthoOpposite( ptC[2] - ptM)} elseif nSide == -1 then vOrd = EgtIf( ptC[1]:getY() < ptRef:getY(), { 1, 2}, { 2, 1}) local vtFaceUse1, vtFaceUse2 if bCanUseBlade and not BD.DOWN_HEAD then bIsMachDownUp = true vtFaceUse1 = BL.GetOrtupOpposite( BL.GetNearestOrthoOpposite( ptC[1] - ptM)) vtFaceUse2 = BL.GetOrtupOpposite( BL.GetNearestOrthoOpposite( ptC[2] - ptM)) else vtFaceUse1 = BL.GetNearestParalOpposite( ptC[1] - ptM) vtFaceUse2 = BL.GetNearestParalOpposite( ptC[2] - ptM) end vFaceUse = { vtFaceUse1, vtFaceUse2} else local bFront = ( ( vtN[1]:getY() + vtN[2]:getY()) < 0) if bFront then vOrd = EgtIf( ptC[1]:getZ() < ptRef:getZ(), { 1, 2}, { 2, 1}) vFaceUse = { BL.GetNearestOrthoOpposite( ptC[1] - ptM), BL.GetNearestOrthoOpposite( ptC[2] - ptM)} else vOrd = EgtIf( ptC[1]:getZ() < ptRef:getZ(), { 2, 1}, { 1, 2}) vFaceUse = { BL.GetNearestOrthoOpposite( ptC[1] - ptM), BL.GetNearestOrthoOpposite( ptC[2] - ptM)} end end local vWidth = {} _, _, vWidth[1] = BL.GetFaceHvRefDim( Proc.Id, tFaceLong[1]) _, _, vWidth[2] = BL.GetFaceHvRefDim( Proc.Id, tFaceLong[2]) local vElevation = { vWidth[2], vWidth[1]} -- Se da sopra o ( da tutte i lati con testa da sotto) e taglio di lama e lunghezza facce maggiore del parametro lunghezza minima if ( bCanUseUnderBlade or bCanUseBlade) and bUseBlade and Proc.Box:getDimX() > dLimMinPiece - 1 then local sCutting local dToolDiam = 0 local dToolThick = 0 local dMaxDepth = 0 local sCuttingDn local dToolDiamDn = 0 local dToolThickDn = 0 local dMaxDepthDn = 0 -- recupero la lavorazione if bCanUseUnderBlade then sCuttingDn = ML.FindCutting( 'HeadSide_H2', false, true) if not sCuttingDn then local sErr = 'Error on process ' .. tostring( Proc.Id) .. ' sawing underneath not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile if EgtMdbSetCurrMachining( sCuttingDn) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiamDn = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiamDn dToolThickDn = EgtTdbGetCurrToolParam(MCH_TP.THICK) or dToolThickDn dMaxDepthDn = EgtTdbGetCurrToolMaxDepth() or dMaxDepthDn end end end if bCanUseBlade then local sCutType = EgtIf( BD.USE_LONGCUT, 'LongCut', 'HeadSide') sCutting = ML.FindCutting( sCutType) if not sCutting then local sErr = 'Error : sawing '..sCutType..' not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dToolThick = EgtTdbGetCurrToolParam(MCH_TP.THICK) or dToolThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end end -- se la fine (a sinistra) non è limitata e ho un pezzo successivo o grezzo riutilizzabile meno distante di metà raggio, setto la fine come limitata if (( bCanUseBlade or bCanUseUnderBlade) and ( dDistToNextPiece < dToolDiam/2 or dDistToNextPiece < dToolDiamDn/2)) and nFaceLimit < 2 then if bForceUseBladeOnNotThruFace then nFaceLimit = nFaceLimit | 2 bForcedLim = true else sWarn = 'Warning on saw cut : Cut machining can damage next piece' EgtOutLog( sWarn) end end -- determino gli estremi local dStartAccDist local dEndAccDist local bStartFixed local bEndFixed local dStartDist local dEndDist local dStartDistUp = 0 local dEndDistUp = 0 local dStartDistDn = 0 local dEndDistDn = 0 local dStartAccDistUp = BD.LONGCUT_ENDLEN local dEndAccDistUp = BD.LONGCUT_ENDLEN local dStartAccDistDn = BD.LONGCUT_ENDLEN local dEndAccDistDn = BD.LONGCUT_ENDLEN local nC local dC local nCUp local dCUp -- determino numero di parti if bCanUseBlade then nCUp = ceil( ( dLen - dStartAccDistUp - dEndAccDistUp) / BD.LONGCUT_MAXLEN) dCUp = 0 if nCUp > 0 then dCUp = ( dLen - dStartAccDistUp - dEndAccDistUp) / nCUp if dCUp < min( dStartAccDistUp, dEndAccDistUp) then dCUp = dLen / ( nCUp + 2) dStartAccDistUp = dCUp dEndAccDistUp = dCUp end nCUp = nCUp + 2 else if dLen > min( dStartAccDistUp, dEndAccDistUp) then nCUp = 2 dStartAccDistUp = dLen / 2 dEndAccDistUp = dStartAccDistUp else nCUp = 1 dStartAccDistUp = 0 dEndAccDistUp = 0 end end end local nCDn local dCDn if bCanUseUnderBlade then nCDn = ceil( ( dLen - dStartAccDistDn - dEndAccDistDn) / BD.LONGCUT_MAXLEN) dCDn = 0 if nCDn > 0 then dCDn = ( dLen - dStartAccDistDn - dEndAccDistDn) / nCDn if dCDn < min( dStartAccDistDn, dEndAccDistDn) then dCDn = dLen / ( nCDn + 2) dStartAccDistDn = dCDn dEndAccDistDn = dCDn end nCDn = nCDn + 2 else if dLen > min( dStartAccDistDn, dEndAccDistDn) then nCDn = 2 dStartAccDistDn = dLen / 2 dEndAccDistDn = dStartAccDistDn else nCDn = 1 dStartAccDistDn = 0 dEndAccDistDn = 0 end end end -- prendo il valore minimo di passi if nCUp then nC = nCUp dC = dCUp elseif nCDn then nC = nCDn dC = dCDn end -- uso codolo piccolo local dDimStrip = BD.DIM_STRIP_SMALL * EgtIf( nSide == -1, -1, 1) local nM = 0 -- se convesso lavoro ogni faccia in due metà lasciando attaccata la parte centrale if bConvex then -- si percorrono i lati alto e basso della faccia for i = 1, nC do -- Posizione braccio portatesta local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = EgtIf( ( i == 1 or i == nC - 1), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) end local nCountToShift = 0 local bChangeBlade local bMachDownGen -- ciclo sulle due facce for j = 1, #vOrd do local nIdPrev local nIdNext nCountToShift = nCountToShift + 1 -- determino se lavorazione da davanti o da dietro local bFront = ( vtN[vOrd[j]]:getY() < 0) -- determino se posso usare lame sulla faccia specifica bCanUseBlade, bCanUseUnderBlade = CalcBladeUse( bUseBlade, BD.DOWN_HEAD, nSide, vtN[vOrd[j]], nil, bConvex, j, bFront) if not bCanUseUnderBlade and not bCanUseBlade then local sErr = 'Error : impossible use blade on too negative face' EgtOutLog( sErr) return false, sErr end local nFaceUse local nFaceUse2 -- se ho solo lama da sotto if bCanUseUnderBlade and not bCanUseBlade then -- determino l'utilizzo della faccia nFaceUse = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_TOP, EgtIf( bFront, MCH_MILL_FU.ORTHO_FRONT, MCH_MILL_FU.ORTHO_BACK)) nFaceUse2 = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_DOWN, EgtIf( bFront, MCH_MILL_FU.ORTHO_BACK, MCH_MILL_FU.ORTHO_FRONT)) else -- determino l'utilizzo della faccia nFaceUse = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_TOP, EgtIf( bFront, MCH_MILL_FU.ORTHO_BACK, MCH_MILL_FU.ORTHO_FRONT)) nFaceUse2 = EgtIf( abs( vtN[vOrd[j]]:getY()) > 0.01, MCH_MILL_FU.ORTHO_DOWN, EgtIf( bFront, MCH_MILL_FU.ORTHO_FRONT, MCH_MILL_FU.ORTHO_BACK)) end -- se lama da sotto verifico se la componente Y della profondità di taglio supera la capacità della lama if nSide <= 0 and bCanUseUnderBlade then if (( vWidth[vOrd[j]] - dDimStrip) / 2) > dMaxDepthDn then local sErr = 'Error : side depth is bigger than underneath blade cut depth' EgtOutLog( sErr) return false, sErr end end local dOffset = ( vWidth[vOrd[j]] + dDimStrip) / 2 ; local dLioTang = 0 local nFaceSide = 0 if vtN[vOrd[j]]:getZ() > 0.707 then nFaceSide = 1 elseif vtN[vOrd[j]]:getZ() < -0.707 then nFaceSide = -1 end -- ricavo informazioni della faccia local b3Fac = EgtSurfTmGetFacetBBoxGlob( Proc.Id, vOrd[j]-1, GDB_BB.STANDARD) -- determino accorciamenti se lavorazione cieca if bForceUseBladeOnNotThruFace then if bCanUseBlade then bStartFixed = true -- limitato a destra if ( nFaceLimit & 1) ~= 0 then local dRadius = dToolDiam / 2 local dCat1 = dRadius - dOffset dStartDistUp = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) bStartFixed = false end bEndFixed = true -- limitato a sinistra if ( nFaceLimit & 2) ~= 0 then local dRadius = dToolDiam / 2 local dCat1 = dRadius - dOffset dEndDistUp = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) bEndFixed = false end end if bCanUseUnderBlade then bStartFixed = true -- limitato a destra if ( nFaceLimit & 1) ~= 0 then local dRadius = dToolDiamDn / 2 local dCat1 = dRadius - dOffset dStartDistDn = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) bStartFixed = false end bEndFixed = true -- limitato a sinistra if ( nFaceLimit & 2) ~= 0 then local dRadius = dToolDiamDn / 2 local dCat1 = dRadius - dOffset dEndDistDn = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) bEndFixed = false end end end -- ciclo sulle passate for k = 1, 2 do local dLioPerp = ( vWidth[vOrd[j]] - dDimStrip) / 2 + BD.CUT_SIC -- inserisco le parti di lavorazione nM = nM + 1 local sNameF local nMchFId local sCuttingName local bMachDown if bCanUseBlade and not bCanUseUnderBlade then sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCutting) sCuttingName = sCutting -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistUp dStartAccDist = dStartAccDistUp dStartDist = dStartDistUp dEndDist = dEndDistUp elseif bCanUseUnderBlade and not bCanUseBlade then sNameF = 'L2CD_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCuttingDn) sCuttingName = sCuttingDn -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistDn dStartAccDist = dStartAccDistDn dStartDist = dStartDistDn dEndDist = dEndDistDn bMachDown = true -- entrambe le possibilità di lama else -- se di fronte e prima faccia o dietro e seconda faccia, sta lavorando quella più in basso in Z (posizione) if ( ( bFront and j == 1) or ( not bFront and j == 2)) and k == 1 then -- prediligo quella inferiore sNameF = 'L2CD_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCuttingDn) sCuttingName = sCuttingDn -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistDn dStartAccDist = dStartAccDistDn dStartDist = dStartDistDn dEndDist = dEndDistDn bMachDown = true -- se di fronte e prima faccia o dietro e seconda faccia, sta lavorando quella più in basso in Z (posizione) elseif ( ( bFront and j == 1) or ( not bFront and j == 2)) and k == 2 then sNameF = 'L2CD_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCuttingDn) sCuttingName = sCuttingDn -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistDn dStartAccDist = dStartAccDistDn dStartDist = dStartDistDn dEndDist = dEndDistDn bMachDown = true -- se di fronte e seconda faccia o dietro e prima faccia, sta lavorando la faccia più in alto in Z (posizione) elseif ( ( bFront and j == 2) or ( not bFront and j == 1)) and k == 1 then sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCutting) sCuttingName = sCutting -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistUp dStartAccDist = dStartAccDistUp dStartDist = dStartDistUp dEndDist = dEndDistUp -- se di fronte e seconda faccia o dietro e prima faccia, sta lavorando la faccia più in alto in Z (posizione) elseif ( ( bFront and j == 2) or ( not bFront and j == 1)) and k == 2 then sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCutting) sCuttingName = sCutting -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistUp dStartAccDist = dStartAccDistUp dStartDist = dStartDistUp dEndDist = dEndDistUp end end if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sCuttingName EgtOutLog( sErr) return false, sErr end if j == 1 and k == 1 then bMachDownGen = bMachDown else if bMachDownGen ~= bMachDown then bChangeBlade = true end end local bAddOpposite = true local dAddExtraPerp = 0 if ( nFaceSide == -1 and abs(vtN[vOrd[j]]:getY()) >= 0.2079) then bAddOpposite = false end if ( nFaceSide == 0 and abs(vtN[vOrd[j]]:getZ()) >= 0.2588) then bAddOpposite = false end if ( nFaceSide == 1 and not bMachDown) or ( nFaceSide == -1 and bMachDown) or ( nFaceSide == -1 and k == 1) then bAddOpposite = false end if bAddOpposite then -- controllo se devo aggiungere un extra all'attacco perpendicolare if nFaceSide == -1 then if vtN[vOrd[j]]:getY() > 0 then dAddExtraPerp = b3Fac:getMin():getY() - b3Solid:getMin():getY() elseif vtN[vOrd[j]]:getY() < 0 then dAddExtraPerp = b3Solid:getMax():getY() - b3Fac:getMax():getY() end elseif nFaceSide == 0 then if ( ( bFront and j == 1) or ( not bFront and j == 2)) and vtN[vOrd[j]]:getZ() <= 0 and k == 2 then dAddExtraPerp = b3Solid:getMax():getZ() - b3Fac:getMax():getZ() elseif ( ( bFront and j == 2) or ( not bFront and j == 1)) and vtN[vOrd[j]]:getZ() >= 0 and k == 1 then dAddExtraPerp = b3Fac:getMin():getZ() - b3Solid:getMin():getZ() end end dLioPerp = dLioPerp + dAddExtraPerp end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vOrd[j]-1}}) -- settaggio di workside, uso faccia e eventuale inversione -- limito opportunamente la lavorazione local dSalInner, dSalOuter = - dEndAccDist - ( i - 2) * dC, -dEndDist local dEalInner, dEalOuter = - dStartAccDist - ( nC - i - 1) * dC, -dStartDist local dSal = EgtIf( i == 1, dSalOuter, dSalInner) local dEal = EgtIf( i == nC, dEalOuter, dEalInner) if ( bFront and k == 1) or ( not bFront and k == 2) then dSal, dEal = dEal, dSal end -- verifico lama in uso e imposto uso faccia local bIsTopBladeCurrent = not bMachDown local nFaceUseCurrent if bCanUseBlade and bCanUseUnderBlade then if nSide == -1 then dSal, dEal = dEal, dSal if k == 1 then nFaceUseCurrent = nFaceUse2 else nFaceUseCurrent = nFaceUse end else if k == 1 then nFaceUseCurrent = nFaceUse else nFaceUseCurrent = nFaceUse2 end end elseif bCanUseUnderBlade then if k == 1 then nFaceUseCurrent = nFaceUse else nFaceUseCurrent = nFaceUse2 end else if k == 1 then nFaceUseCurrent = nFaceUse else nFaceUseCurrent = nFaceUse2 end end -- recupero alcune informazioni utili dalla lavorazione attuale local bIsCurrentBladeCCW local sCuttingNameMach if bIsTopBladeCurrent then sCuttingNameMach = sCutting else sCuttingNameMach = sCuttingDn end EgtMdbSetCurrMachining( sCuttingNameMach) bIsCurrentBladeCCW = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) < 0 -- imposto la direzione di lavoro per avere scarico del truciolo ottimale local nWorkSide, bInvert if ( not bIsTopBladeCurrent and abs( nSide) ~= 0) or ( bCanUseBlade and bCanUseUnderBlade and nSide == -1) then if bIsCurrentBladeCCW and not bIsMachDownUp then nWorkSide = MCH_MILL_WS.LEFT bInvert = true dSal, dEal = dEal, dSal else nWorkSide = MCH_MILL_WS.RIGHT bInvert = false end else if bIsCurrentBladeCCW and not bIsMachDownUp then nWorkSide = MCH_MILL_WS.LEFT bInvert = false else nWorkSide = MCH_MILL_WS.RIGHT bInvert = true dSal, dEal = dEal, dSal end end -- setto la lavorazione con i valori calcolati EgtSetMachiningParam( MCH_MP.INVERT, bInvert) EgtSetMachiningParam( MCH_MP.WORKSIDE, nWorkSide) EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUseCurrent) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, EgtIf( nSide == -1, -dOffset, dOffset)) -- imposto attacco/uscita EgtSetMachiningParam( MCH_MP.LITANG, dLioTang) EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOTANG, dLioTang) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto angolo 3° asse rot local vtOut = EgtIf( vtN[vOrd[j]]:getX() > 0, X_AX(), -X_AX()) EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( sCuttingNameMach, 'perpendicular', b3Raw, vtN, vtOut)) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- se sono alla seconda faccia scambio le ultime due lavorazione per ottimizzare i percorosi if nCountToShift == 2 then -- se prima porzione di faccia memorizzo l'id della lavorazione if k == 1 then nIdPrev = nMchFId else nIdNext = nMchFId end -- alla fine della seconda porzione della seconda faccia se non ho cambiato utensile tra le facce sposta la prima dopo la seconda if nIdPrev and nIdNext and k == 2 and not bChangeBlade then EgtRelocateGlob( nIdPrev, nIdNext, GDB_IN.AFTER) end end end end end -- eventuali puliture impronta lama for j = 1, #vOrd do if bForceUseBladeOnNotThruFace then -- determino la massima elevazione local dElev = 0 local dFacElev1 = BL.GetFaceElevation( Proc, tFaceLong[1], b3Solid) local dFacElev2 = BL.GetFaceElevation( Proc, tFaceLong[2], b3Solid) dElev = max( dFacElev1, dFacElev2) -- recupero la lavorazione local sMilling local bDownHead = ( nSide == -1 and BD.DOWN_HEAD) sMilling = ML.FindMilling( 'Long2Cut', dElev, nil, nil, nil, not bDownHead, bDownHead) if not sMilling then local sErr = 'Error : Long2Cut not found in library' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dToolDiam = 0 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sMilling) 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 end -- eventuale lavorazione della faccia limitante l'inizio (a destra) if not bStartFixed then MakeSideFace( Proc.Id, tFaceLong[vOrd[j]], 1, j, sMilling, dToolDiam, nSide, bIsAnyFaceUpsideDown) end -- eventuale lavorazione della faccia limitante la fine (a sinistra) if not bEndFixed then MakeSideFace( Proc.Id, tFaceLong[vOrd[j]], -1, j, sMilling, dToolDiam, nSide, bIsAnyFaceUpsideDown) end end end -- altrimenti concavo else -- si percorrono i lati alto e basso della faccia for i = 1, nC do -- Posizione braccio portatesta local nSCC = MCH_SCC.NONE if not BD.C_SIMM then nSCC = EgtIf( ( i == 1 or i == nC - 1), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) end -- ciclo sulle due facce for j = 1, #vOrd do -- determino se lavorazione da davanti o da dietro local bFront = ( vtN[vOrd[j]]:getY() < 0) local OthFace = abs(j-3) local dSinLimit -- se faccia da sotto e Z centro faccia è minore del centro altra faccia, segno il limite angolare da passare -- dovrebbe essere il limite angolare della testa 1 in sottosquadra if nSide == -1 and not BD.DOWN_HEAD then if ptC[vOrd[j]]:getZ() < ptC[vOrd[OthFace]]:getZ() - 1. then dSinLimit = -0.0157 else dSinLimit = -0.5 end end -- determino se posso usare lame sulla faccia specifica bCanUseBlade, bCanUseUnderBlade = CalcBladeUse( bUseBlade, BD.DOWN_HEAD, nSide, vtN[vOrd[j]], nil, bConvex, j, bFront, dSinLimit) if not bCanUseUnderBlade and not bCanUseBlade then local sErr = 'Error : impossible use blade on too negative face' EgtOutLog( sErr) return false, sErr end -- se effettivamente un taglio longitudinale e lama non taglia completamente, limito la lavorazione. Altrimenti esco. local dCheckDepth = 0 if bCanUseBlade then dCheckDepth = dMaxDepth elseif bCanUseUnderBlade then dCheckDepth = dMaxDepthDn end if vWidth[vOrd[j]] + 100 * GEO.EPS_SMALL > dCheckDepth then if not( ProcessLong2Cut.Identify( Proc)) then return false else local sWarn2 = 'Warning in ' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. ' : elevation (' .. EgtNumToString( vWidth[vOrd[j]], 1) .. ') bigger than max saw depth (' .. EgtNumToString( dCheckDepth, 1) .. ')' if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end end -- se lama da sotto verifico se la componente Y della profondità di taglio supera la capacità della lama if nSide <= 0 and bCanUseUnderBlade then if ( vWidth[vOrd[j]] / 2) > dMaxDepthDn then local sErr = 'Error : side depth is bigger than underneath blade cut depth' EgtOutLog( sErr) return false, sErr end end -- ciclo sulle passate local dOffset local dLioPerp if j == 1 then -- il primo taglio lo faccio completo se angolo interno maggiore di 90 local dMinOffsBigFace = max( vWidth[vOrd[j]] - dCheckDepth, 0) -- se la faccia è più grande del massimo materiale lama, allora limito lavorazione if dMinOffsBigFace > 0 then dOffset = dMinOffsBigFace -- se angolo interno inferiore di 90° calcolo l'arretramento della lama + un piccolo delta di 0.3 elseif dAng < - ( 90 + 10 * GEO.EPS_SMALL) then dOffset = 0.3 + ((dToolThick* vtN[vOrd[1]]) * vtN[vOrd[2]] * vtN[vOrd[2]]):len() else dOffset = 0 end dLioPerp = vWidth[vOrd[j]] + BD.CUT_SIC else -- il secondo ridotto della distanza minima e della componente spessore della lama local dMinOffsBigFace = max( vWidth[vOrd[j]] - dCheckDepth, 0) -- se la faccia è più grande del massimo materiale lama, allora limito lavorazione if dMinOffsBigFace > 0 then dOffset = dMinOffsBigFace else dOffset = dDimStrip + ((dToolThick* vtN[vOrd[1]]) - (dToolThick* vtN[vOrd[1]]) * vtN[vOrd[2]] * vtN[vOrd[2]]):len() end dLioPerp = vWidth[vOrd[j]] - dOffset + BD.CUT_SIC end local dLioTang = 0 local sNameF local nMchFId nM = nM + 1 if bCanUseBlade then sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCutting) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sCutting EgtOutLog( sErr) return false, sErr end -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistUp dStartAccDist = dStartAccDistUp elseif bCanUseUnderBlade then sNameF = 'L2CD_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring(j) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sCuttingDn) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sCuttingDn EgtOutLog( sErr) return false, sErr end -- setto le variabili delle distanze dagli estremi dEndAccDist = dEndAccDistDn dStartAccDist = dStartAccDistDn end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, vOrd[j]-1}}) -- limito opportunamente la lavorazione local dSal = EgtIf( i == nC, 0, - dEndAccDist - ( nC - i - 1) * dC) local dEal = EgtIf( i == 1, 0, - dStartAccDist - ( i - 2) * dC) if j == 2 then dSal, dEal = dEal, dSal end if nSide == -1 and BD.DOWN_HEAD then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) elseif nSide == -1 and not BD.DOWN_HEAD and bIsMachDownUp then EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( EgtGetMachiningParam( MCH_MP.INVERT), false, true)) dOffset = 5 EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) end -- imposto offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, dOffset) -- imposto attacco/uscita EgtSetMachiningParam( MCH_MP.LITANG, dLioTang) EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOTANG, dLioTang) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) -- imposto posizione braccio porta testa per non ingombrare agli estremi local ptP1LineToMachine, _, ptP2LineToMachine = EgtSurfTmFacetOppositeSide( Proc.Id, vOrd[j] - 1, BL.GetVersRef( vFaceUse[vOrd[j]]), GDB_ID.ROOT) local vtTg = ptP2LineToMachine - ptP1LineToMachine ; vtTg:normalize() local bIsMachiningInverted = EgtGetMachiningParam( MCH_MP.INVERT) if bIsMachiningInverted then vtTg = -vtTg end if BD.C_SIMM then if abs( vtN[vOrd[j]]:getX()) < GEO.EPS_SMALL then nSCC = EgtIf( ( vtTg:getX() > GEO.EPS_SMALL), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) else nSCC = MCH_SCC.NONE end else nSCC = EgtIf( ( i == 1 or i == nC - 1), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) end EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- determino e imposto l'utilizzo della faccia EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse[vOrd[j]]) -- imposto angolo 3° asse rot local vtOut = EgtIf( vtN[vOrd[j]]:getX() > 0, X_AX(), -X_AX()) EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( EgtIf( bCanUseUnderBlade, sCuttingDn, sCutting), 'perpendicular', b3Raw, vtN, vtOut)) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end end -- se non è sotto e non uso fresa di fianco: lavorazione Long2Cut elseif ( nSide ~= -1 or BD.DOWN_HEAD or BD.TURN) and nUseMillOnSide == 0 then -- determino la massima elevazione local dElev = 0 -- calcolo l'elevazione della faccia principale local dFacElev1 = BL.GetFaceElevation( Proc, tFaceLong[vOrd[1]], b3Solid) local dFacElev2 = BL.GetFaceElevation( Proc, tFaceLong[vOrd[2]], b3Solid) local bFacesSwapped = false if bInt and not bConvex and dFacElev1 - 10* GEO.EPS_SMALL > dFacElev2 then vOrd[1], vOrd[2] = vOrd[2], vOrd[1] dFacElev1, dFacElev2 = dFacElev2, dFacElev1 bFacesSwapped = true end -- se facce concave e a 90 gradi, prendo l'elevazione minima if bOrtho then dElev = min( dFacElev1, dFacElev2) else dElev = max( dFacElev1, dFacElev2) end -- recupero la lavorazione local sMilling local bDownHead = ( BD.DOWN_HEAD and ( nSide == -1 or AreSameVectorApprox( vtN[vOrd[1]], -Z_AX()))) sMilling = ML.FindMilling( 'Long2Cut', dElev, nil, nil, nil, not bDownHead, bDownHead) if not sMilling then local sErr = 'Error : Long2Cut not found in library' EgtOutLog( sErr) return false, sErr end -- se angolo compreso è inferiore ai 90 gradi do errore if dAng and dAng < - ( 90 + 10 * GEO.EPS_ANG_SMALL) then local sErr = 'Error : Impossible use a mill with angle less than 90' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dToolDiam = 0 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sMilling) 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 end -- se ho un pezzo successivo più distante di metà raggio : setto la fine come limitata if dDistToNextPiece < dToolDiam/2 then bForcedLim = true nFaceLimit = nFaceLimit | 2 end -- se chiuso e corto, applico svuotatura con fresa opportuna if nFaceLimit == 3 and Proc.Box:getDimX() < 2 * dToolDiam then -- svuotatura della prima faccia longitudinale local bOk, sErr = MakeByPocketing( Proc, nPhase, nRawId, nPartId, nSide, tFaceLong[vOrd[1]], dFacElev1) -- svuotatura della seconda faccia longitudinale if not bOk then return bOk, sErr end return MakeByPocketing( Proc, nPhase, nRawId, nPartId, nSide, tFaceLong[vOrd[2]], dFacElev2) end -- determino gli estremi local dStartDist = 0 local dStartAccDist = BD.LONGCUT_ENDLEN local bStartFixed = true -- se ho faccia limite a destra if nFaceLimit == 1 or nFaceLimit == 3 then dStartDist = dToolDiam / 2 dStartAccDist = BD.LONGCUT_MAXLEN bStartFixed = false end local dEndDist = 0 local dEndAccDist = BD.LONGCUT_ENDLEN local bEndFixed = true -- se ho faccia limite a sinistra if nFaceLimit >= 2 then dEndDist = dToolDiam / 2 dEndAccDist = BD.LONGCUT_MAXLEN bEndFixed = false end -- determino il numero di parti in cui dividere la lavorazione local nC = ceil( ( dLen - dStartAccDist - dEndAccDist) / BD.LONGCUT_MAXLEN) local dC = 0 if nC > 0 then local nIncStep = 2 if bStartFixed and bEndFixed then dC = ( dLen - dStartAccDist - dEndAccDist) / nC -- se distanza rimanente è < della metà del minimo della distanza estremi allora aggiungo un solo passo in più local dMinDist = EgtIf( min( dStartAccDist, dEndAccDist) / 2 > 300 , 300, min( dStartAccDist, dEndAccDist) / 2) if dC < dMinDist then dC = dLen / ( nC + 1) dStartAccDist = dC dEndAccDist = dC nIncStep = 1 elseif dC < min( dStartAccDist, dEndAccDist) then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end elseif bStartFixed then dC = ( dLen - dStartAccDist) / ( nC + 1) dEndAccDist = dC if dC < dStartAccDist then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end elseif bEndFixed then dC = ( dLen - dEndAccDist) / ( nC + 1) dStartAccDist = dC if dC < dEndAccDist then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end else dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end nC = nC + nIncStep else if dLen > min( dStartAccDist, dEndAccDist) then nC = 2 if bStartFixed and not bEndFixed then dStartAccDist = min( dStartAccDist, dLen/2) dEndAccDist = dLen - dStartAccDist elseif not bStartFixed and bEndFixed then dEndAccDist = min( dEndAccDist, dLen/2) dStartAccDist = dLen - dEndAccDist else -- se c'è del grezzo aggiuntivo e, considerando il grezzo mi resta abbastanza materiale per pinzare, allora faccio spezzatura asimmetrica if BD.MIN_CLAMPING_LEN and ( dBarLen - dLen) > dOvmHead + 100 * GEO.EPS_SMALL and ( dBarLen - dStartAccDist > BD.MIN_CLAMPING_LEN) then dStartAccDist = dBarLen/2 dEndAccDist = dLen - dStartAccDist else dStartAccDist = dLen/2 dEndAccDist = dStartAccDist end end else nC = 1 dStartAccDist = 0 dEndAccDist = 0 end end local nIni, nFin = 1, 2 local dLimitAngle = -0.5 - 20 * GEO.EPS_SMALL -- se facce ortogonali (concave), mantengo la lavorazione di testa sulla faccia più grande purchè non superi di 30 gradi il sottosquadra if bOrtho then if bDownHead and AreSameVectorApprox( vtN[vOrd[1]], -Z_AX()) then nFin = 1 else local vtN1 = vtN[vOrd[1]] local vtN2 = vtN[vOrd[2]] if vtN1:getZ() > 0.001 and vtN2:getZ() > 0.001 then if vtN1:getZ() >= vtN2:getZ() then nFin = 1 else nIni = 2 end else if vtN1:getZ() < dLimitAngle then nIni = 2 elseif vtN2:getZ() < dLimitAngle then nFin = 1 else if vtN1:getZ() >= vtN2:getZ() then if vtN1:getZ() < dLimitAngle then nIni = 2 else nFin = 1 end else if vtN1:getZ() < dLimitAngle then nIni = 2 else nFin = 1 end end end end end end if Proc.bMoveAfterSplit then nC = 1 dStartDist = Proc.Box:getDimX() - ( dToolDiam / 2 + 5) dEndDist = - ( dToolDiam / 2 + 5) end if nIni == 2 then dStartDist, dEndDist = dEndDist, dStartDist dStartAccDist, dEndAccDist = dEndAccDist, dStartAccDist end -- ciclo sulle parti local nM = 0 local bInverted = false for j = 1, nC do -- su entrambe le facce for i = nIni, nFin do -- valore sovrapposizione tra passate con fresa di fianco local dOverLapExtend = 2 -- Verifico se da fare di fianco perchè normale troppo verso il basso (minore di -30deg) local bSide = ( vtN[vOrd[i]]:getZ() < dLimitAngle and not ( bDownHead or ( nSide == -1 and ( BD.DOWN_HEAD or BD.TURN)))) -- Limitazioni della lavorazione local nPos = EgtIf( i == 1, j, nC - j + 1) local dSal = EgtIf( nPos == 1, - EgtIf( i == nIni, dStartDist, dEndDist), - EgtIf( i == nIni, dStartAccDist, dEndAccDist) - ( nPos - 2) * dC + EgtIf( bSide, dOverLapExtend, 0)) local dEal = EgtIf( nPos == nC, - EgtIf( i == nIni, dEndDist, dStartDist), - EgtIf( i == nIni, dEndAccDist, dStartAccDist) - ( nC - nPos - 1) * dC + EgtIf( bSide, dOverLapExtend, 0)) if nSide == -1 then dSal, dEal = dEal, dSal end -- Posizione braccio portatesta local nSCC = MCH_SCC.NONE if not BD.C_SIMM then if not BD.TURN then nSCC = EgtIf( ( j == 1 or j == nC - 1), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) else if nSide == 1 or nSide == -1 then local bFromYM = (( vtN[vOrd[i]]:getY() < 0 and bConvex) or ( vtN[vOrd[i]]:getY() > 0 and not bConvex)) nSCC = EgtIf( bFromYM, MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP) if BD.TURN == 2 and not bFromYM then nSCC = EgtIf( nSide == -1, MCH_SCC.ADIR_ZM, MCH_SCC.ADIR_ZP) end else local bFromZM = (( vtN[vOrd[i]]:getZ() < 10 * GEO.EPS_ANG_SMALL and bConvex) or ( vtN[vOrd[i]]:getZ() > - 10 * GEO.EPS_ANG_SMALL and not bConvex)) nSCC = EgtIf( bFromZM, MCH_SCC.ADIR_ZM, MCH_SCC.ADIR_ZP) end end end if bSide and not bConvex then dSal, dEal = dEal, dSal end -- ciclo sulle passate local nO = 1 local dStep = 0 local dAgg = EgtIf( bConvex, 2 * BD.CUT_EXTRA, BD.CUT_EXTRA) local dLargh = vWidth[vOrd[i]] -- controllo se lavorazione completa local dMachDepth = vElevation[vOrd[i]] if dMachDepth > dMaxDepth - 10 * GEO.EPS_ANG_SMALL then -- verifico se posso lavorare la faccia 2 local nOtherFace = EgtIf( i == 1, 2, 1) if Proc.Fct == 2 and j == 1 and vtN[vOrd[nOtherFace]]:getZ() > dLimitAngle and vWidth[vOrd[i]] < dMaxDepth then vOrd[1], vOrd[2] = vOrd[2], vOrd[1] dLargh = vWidth[vOrd[i]] dSal, dEal = dEal, dSal bInverted = true else sWarn = 'Warning : elevation bigger than max tool depth' EgtOutLog( sWarn) end elseif bInverted then dSal, dEal = dEal, dSal end if not bSide and dLargh > 0.8 * dToolDiam then nO = ceil( dLargh / ( 0.6 * dToolDiam)) if nO > 1 then dStep = dLargh / nO end end for k = 1, nO do -- inserisco le parti di lavorazione nM = nM + 1 local sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) local nMchFId = EgtAddMachining( sNameF, sMilling) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end local dMySal, dMyEal = dSal, dEal if bFacesSwapped then dMySal, dMyEal = dMyEal, dMySal end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, tFaceLong[vOrd[i]]}}) -- limito opportunamente la lavorazione if ( nSide == -1 and BD.DOWN_HEAD) then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dMyEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dMySal) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, dMySal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dMyEal) end -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto uso faccia EgtOutLog( 'FaceUse='..tostring( vFaceUse[vOrd[i]])) --EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bSide, BL.GetParallelOpposite( vFaceUse[vOrd[i]]), vFaceUse[vOrd[i]])) EgtSetMachiningParam( MCH_MP.FACEUSE, EgtIf( bSide, MCH_MILL_FU.PARAL_DOWN, vFaceUse[vOrd[i]])) -- imposto lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bIsMachDownUp, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)) EgtSetMachiningParam( MCH_MP.INVERT, EgtIf( bSide, true, false)) -- si aggiusta la direzione di lavoro in base a rotazione utensile e preferenza utente (nUseConventionalMilling da fuori o Q14) EgtMdbSetCurrMachining( sMilling) local bIsCurrentToolCCW = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) < 0 if nUseConventionalMilling == nil then nUseConventionalMilling = EgtGetInfo( Proc.Id, 'Q14', 'd') or 0 end local bUseConventionalMilling = false if nUseConventionalMilling == 1 or ( nUseConventionalMilling == 2 and vtN[vOrd[i]]:getX() < 0.1 and Proc.AffectedFaces.Bottom) then bUseConventionalMilling = true end if bIsCurrentToolCCW ~= bUseConventionalMilling then local dCurrStartAddLen = EgtGetMachiningParam( MCH_MP.STARTADDLEN) local dCurrEndAddLen = EgtGetMachiningParam( MCH_MP.ENDADDLEN) local bCurrInvert = EgtGetMachiningParam( MCH_MP.INVERT) local nCurrWorkside = EgtGetMachiningParam( MCH_MP.WORKSIDE) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dCurrEndAddLen) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dCurrStartAddLen) EgtSetMachiningParam( MCH_MP.INVERT, not bCurrInvert) EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( nCurrWorkside == MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)) end -- imposto offset radiale (nullo se concavo o di lato) local dOffsR = EgtIf( k < nO, ( nO - k) * dStep, EgtIf( bConvex, - BD.CUT_EXTRA, 0)) if bSide then dOffsR = 0 end EgtSetMachiningParam( MCH_MP.OFFSR, dOffsR) -- se di lato e convesso, imposto offset longitudinale if bSide and bConvex then EgtSetMachiningParam( MCH_MP.OFFSL, - BD.CUT_EXTRA) end -- attacco e uscita local dLioPerp = EgtIf( bSide, dToolDiam, dLargh - dOffsR + BD.CUT_SIC) EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) -- se faccia di fianco e testa da sotto, aumento la sicurezza if nSide == 0 and BD.DOWN_HEAD then EgtSetMachiningParam( MCH_MP.STARTPOS, 80) end -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- se facce principali convesse, eventuale lavorazione della faccia limitante l'inizio (a destra) if bConvex and j == 1 and not bStartFixed then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], 1, i, sMilling, dToolDiam, nSide, bIsAnyFaceUpsideDown) end -- se facce principali convesse, eventuale lavorazione della faccia limitante la fine (a sinistra) if bConvex and j == nC and not bEndFixed then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], -1, i, sMilling, dToolDiam, nSide, bIsAnyFaceUpsideDown) end end end if not Proc.bMoveAfterSplit and not bConvex and Proc.AffectedFaces.Left and Proc.DistanceToNextPart < ( dToolDiam / 2 + 5) 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 local AddId = EgtCopyGlob( Proc.Id, nAddGrpId) or GDB_ID.NULL local AddProc = { Id = AddId, Grp = 0, Prc = 12, Box = Proc.Box, Fct = Proc.Fct, Flg = Proc.Flg, PartId = Proc.PartId, TaskId = Proc.TaskId, CutId = Proc.CutId, bMoveAfterSplit = true} Topology.Classify( AddProc, b3Raw) table.insert( AddedIds, AddProc) end -- altrimenti lavorazione di fianco : Long2CutSide o Long2CutDown else -- da Analisi con Fabio Squaratti 15/09/2020 -- variabile che indica se ripassare sul raggio rimasto dalla lavorazione di fianco local bRemoveToolRadius -- se nExtendMach = 0 la lavorazione rimane arretrata dalla fine della faccia del raggio utensile -- se nExtendMach = 1 la lavorazione arriva fino alla fine faccia (se non ha facce limite) ignorando il pezzo successivo -- se nExtendMach = 2 la lavorazione viene estesa ma arretra per non segnare il pezzo successivo (se non ha facce limite) local nExtendMach -- recupero la lavorazione local sMchType, sMchTypeDn local sMilling, sMillingDn local sPrefix, sPrefixDn if nSide ~= - 1 then sMchType = 'Long2CutSide' sMilling = ML.FindMilling( sMchType) sPrefix = 'L2CS_' nExtendMach = nUseMillOnSide if nUseMillOnSide == 2 then bRemoveToolRadius = true end -- se testa da sotto if nSide ~= 1 and BD.DOWN_HEAD then sMchTypeDn = 'Long2CutSide_H2' sMillingDn = ML.FindMilling( sMchTypeDn, nil, nil, nil, nil, false, true) sPrefixDn = 'L2CSH2_' end -- lavorazione da sotto else sMchType = 'Long2CutDown' sMilling = ML.FindMilling( sMchType) sPrefix = 'L2CD_' nExtendMach = 1 if nUseMillOnSide ~= 1 then nExtendMach = 2 -- arretro il minimo indispensabile per non segnare il pezzo successivo (se non ha facce limite) end -- se testa da sotto if BD.DOWN_HEAD then sMchTypeDn = 'Long2CutDown_H2' sMillingDn = ML.FindMilling( sMchTypeDn, nil, nil, nil, nil, false, true) sPrefixDn = 'L2CDH2_' end end if not sMilling and ( nSide == 1 or not BD.DOWN_HEAD) then local sErr = 'Error : milling '..sMchType..' not found in library' EgtOutLog( sErr) return false, sErr end if not sMilling and not sMillingDn then local sErr = 'Error : milling '..sMchType..' and '..sMchTypeDn..' not found in library' EgtOutLog( sErr) return false, sErr end -- se angolo compreso è inferiore ai 90 gradi do errore if dAng < - ( 90 + 10 * GEO.EPS_SMALL) then local sErr = 'Error : Impossible use a mill with angle less than 90' EgtOutLog( sErr) return false, sErr end -- recupero i dati dell'utensile local dToolDiam = 0 local dToolLength = 0 local dMaxDepth = 0 local dThDiam = 0 local dThLen = 0 local dExtraForSafety = EgtIf( BD.DOWN_HEAD, 8.5, 6.5) -- corrisponde al doppio valore di sicurezza dell'mlpe + 0.5 if EgtMdbSetCurrMachining( sMilling) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam dToolLength = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLength dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth dThDiam = EgtTdbGetCurrToolThDiam() or dThDiam dThLen = EgtTdbGetCurrToolThLength() or dThLen end end -- recupero i dati dell'utensile da sotto local dToolDiamDn = 0 local dToolLengthDn = 0 local dMaxDepthDn = 0 local dThDiamDn = 0 local dThLenDn = 0 if nSide ~= 1 and BD.DOWN_HEAD and EgtMdbSetCurrMachining( sMillingDn) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiamDn = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiamDn dToolLengthDn = EgtTdbGetCurrToolParam( MCH_TP.LEN) or dToolLengthDn dMaxDepthDn = EgtTdbGetCurrToolMaxDepth() or dMaxDepthDn dThDiamDn = (EgtTdbGetCurrToolThDiam() or dThDiamDn) dThLenDn = EgtTdbGetCurrToolThLength() or dThLenDn end end local dDistToEnd = dToolDiam / 2 local dDistToEndDn = dToolDiamDn / 2 -- calcolo l'elevazione della faccia principale local dFacElev1 = BL.GetFaceElevation( Proc, tFaceLong[vOrd[1]], b3Solid) local dFacElev2 = BL.GetFaceElevation( Proc, tFaceLong[vOrd[2]], b3Solid) local bFacesSwapped = false if bInt and not bConvex and dFacElev1 - 10* GEO.EPS_SMALL > dFacElev2 then vOrd[1], vOrd[2] = vOrd[2], vOrd[1] dFacElev1, dFacElev2 = dFacElev2, dFacElev1 bFacesSwapped = true end -- se fresa di fianco o da sotto calcolo quanto l'utensile può andare vicino al limite se l'elevazione della faccia è minore del raggio utensile if nUseMillOnSide <= 1 or nSide == -1 then local dFacElev = max( dFacElev1, dFacElev2) if dFacElev < dDistToEnd then dDistToEnd = sqrt( ( ( dToolDiam / 2) * ( dToolDiam / 2)) - ( ( dToolDiam / 2 - dFacElev) * (dToolDiam / 2 - dFacElev))) end if dFacElev < dDistToEndDn then dDistToEndDn = sqrt( ( ( dToolDiamDn / 2) * ( dToolDiamDn / 2)) - ( ( dToolDiamDn / 2 - dFacElev) * (dToolDiamDn / 2 - dFacElev))) end end -- se la fine è già limitata allora setto per arretrare del raggio utensile if nFaceLimit >= 2 then nExtendMach = 0 -- se la fine non è limitata e ho un pezzo successivo distante meno di metà raggio. setto la fine come limitata elseif ( dDistToNextPiece < dDistToEnd or dDistToNextPiece < dDistToEndDn) and nExtendMach ~= 1 then nFaceLimit = nFaceLimit + 2 end -- aggiuntivo sull'affondamento local dAgg = EgtIf( bConvex, BD.CUT_EXTRA, 0) -- determino gli estremi local dStartDist = 0 local dStartAccDist = BD.LONGCUT_ENDLEN local bStartFixed = true -- se ho facce limite a destra if nFaceLimit == 1 or nFaceLimit == 3 then dStartDist = dDistToEnd dStartAccDist = BD.LONGCUT_MAXLEN bStartFixed = false end local dEndDist = 0 local dEndAccDist = BD.LONGCUT_ENDLEN local bEndFixed = true -- se ho facce limite a sinistra if nFaceLimit >= 2 then dEndDist = EgtIf( nExtendMach == 2, dDistToEnd - dDistToNextPiece + 0.5, dDistToEnd) dEndAccDist = BD.LONGCUT_MAXLEN bEndFixed = false end -- determino il numero di parti in cui dividere la lavorazione local nC = ceil( ( dLen - dStartAccDist - dEndAccDist) / BD.LONGCUT_MAXLEN) local dC = 0 if nC > 0 then local nIncStep = 2 if bStartFixed and bEndFixed then dC = ( dLen - dStartAccDist - dEndAccDist) / nC -- se distanza rimanente è < della metà del minimo della distanza estremi allora aggiungo un solo passo in più local dMinDist = EgtIf( min( dStartAccDist, dEndAccDist) / 2 > 300 , 300, min( dStartAccDist, dEndAccDist) / 2) if dC < dMinDist then dC = dLen / ( nC + 1) dStartAccDist = dC dEndAccDist = dC nIncStep = 1 elseif dC < min( dStartAccDist, dEndAccDist) then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end elseif bStartFixed then dC = ( dLen - dStartAccDist) / ( nC + 1) dEndAccDist = dC if dC < dStartAccDist then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end elseif bEndFixed then dC = ( dLen - dEndAccDist) / ( nC + 1) dStartAccDist = dC if dC < dEndAccDist then dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end else dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end nC = nC + nIncStep else if dLen > min( dStartAccDist, dEndAccDist) then nC = 2 if bStartFixed and not bEndFixed then dStartAccDist = min( dStartAccDist, dLen/2) dEndAccDist = dLen - dStartAccDist elseif not bStartFixed and bEndFixed then dEndAccDist = min( dEndAccDist, dLen/2) dStartAccDist = dLen - dEndAccDist else dStartAccDist = dLen/2 dEndAccDist = dStartAccDist end else nC = 1 dStartAccDist = 0 dEndAccDist = 0 end end if Proc.bMoveAfterSplit then nC = 1 dStartDist = Proc.Box:getDimX() - ( dToolDiam / 2 + 5) dEndDist = - ( dToolDiam / 2 + 5) end -- ciclo sulle parti local nM = 0 for j = 1, nC do local nIni, nFin = 1, 2 local nDir = 1 -- se facce ortogonali (concave) controllo se con la lavorazione della prima faccia il diametro copre la seconda (e non la eseguo) if bOrtho then -- se da sotto scelgo la faccia (lavorata col fianco utensile) con direzione più sottosquadra if nSide == -1 and vtN[vOrd[1]]:getZ() < -0.001 and vtN[vOrd[2]]:getZ() < -0.001 then -- se gli angoli delle due facce sono uguali ( sotto il grado di differenza) sgelgo la faccia più vicina a un fianco if abs(vtN[vOrd[1]]:getZ() - vtN[vOrd[2]]:getZ()) < 0.017 then -- se punto medio più vicino al lato dietro if b3Solid:getMax():getY() - ptM:getY() < ptM:getY() - b3Solid:getMin():getY() then -- se prima faccia più vicina alla faccia dietro eseguo prima questa if ptC[vOrd[1]]:getY() > ptC[vOrd[2]]:getY() then if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end -- se è più lontana inverto la direzione di lavoro else -- inverto la direzione di lavorazione delle facce nDir = -1 nIni, nFin = 2, 1 if dToolDiam > vWidth[vOrd[1]] then nFin = 2 end end -- altrimenti punto medio più vicino al lato davanti else -- se prima faccia più vicina alla faccia dietro inverto la direzione di lavorazione if ptC[vOrd[1]]:getY() > ptC[vOrd[2]]:getY() then -- inverto la direzione di lavorazione delle facce nDir = -1 nIni, nFin = 2, 1 if dToolDiam > vWidth[vOrd[1]] then nFin = 2 end else if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end end end elseif vtN[vOrd[2]]:getZ() < vtN[vOrd[1]]:getZ() then -- inverto la direzione di lavorazione delle facce nDir = -1 nIni, nFin = 2, 1 if dToolDiam > vWidth[vOrd[1]] then nFin = 2 end else if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end end -- in tutti gli altri casi else if dToolDiam > vWidth[vOrd[2]] then nFin = 1 end end end -- ciclo sulle facce selezionate for i = nIni, nFin, nDir do -- valore sovrapposizione tra passate local dOverLapExtend = 2 -- Limitazioni della lavorazione local nPos = EgtIf( i == 1, j, nC - j + 1) local dSal = EgtIf( nPos == 1, - EgtIf( i == nIni, dStartDist, dEndDist), - EgtIf( i == nIni, dStartAccDist, dEndAccDist) - ( nPos - 2) * dC + dOverLapExtend) local dEal = EgtIf( nPos == nC, - EgtIf( i == nIni, dEndDist, dStartDist), - EgtIf( i == nIni, dEndAccDist, dStartAccDist) - ( nC - nPos - 1) * dC + dOverLapExtend) -- Posizione braccio portatesta local nSCC = EgtIf( BD.C_SIMM, MCH_SCC.NONE, MCH_SCC.ADIR_XP) -- inserisco le parti di lavorazione nM = nM + 1 local sNameF local nMchFId local bUseDownHead local bFront = (vtN[vOrd[i]]:getY() < 0) if BD.DOWN_HEAD and nSide ~= 1 then local ptC3 = EgtSurfTmFacetCenter( Proc.Id, tFaceLong[vOrd[i]], GDB_ID.ROOT) local ptDir = ptC3 - ptM ; ptDir:normalize() -- se concave e dal versore Z della faccia (> -20°) o convesso e versore Z ( > -30°) decido se eseguire la lavoraione con la testa da sopra o da sotto if ( not bConvex and vtN[vOrd[i]]:getZ() > -0.9397 and ptDir:getZ() > -0.017) or ( bConvex and vtN[vOrd[i]]:getZ() > -0.866 and ptDir:getZ() > 0) then sNameF = sPrefix .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sMilling) bUseDownHead = false if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end else sNameF = sPrefixDn .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sMillingDn) bUseDownHead = true if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMillingDn EgtOutLog( sErr) return false, sErr end end else sNameF = sPrefix .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) nMchFId = EgtAddMachining( sNameF, sMilling) bUseDownHead = false if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMilling EgtOutLog( sErr) return false, sErr end end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, tFaceLong[vOrd[i]]}}) -- limito opportunamente la lavorazione EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- se fresa di fianco e non da sotto if nUseMillOnSide > 0 and nSide ~= -1 then if bConvex then local vFaceUse2 -- se da sopra if nSide == 1 then if vtN[vOrd[i]]:getZ() > 0.866 then vFaceUse2 = BL.GetNearestParalOpposite( vtN[EgtIf(vOrd[i] == 1, 1, 2)], vtN[EgtIf(vOrd[i] == 1, 2, 1)]) EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse2) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) else EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) end -- altrimenti è di fianco else if vtN[vOrd[i]]:getY() > 0.866 then EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_TOP) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) else EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) end end -- se concavo else local vFaceUse2 -- se da sopra if nSide == 1 then vFaceUse2 = BL.GetNearestParalOpposite( vtN[EgtIf(vOrd[i] == 1, 2, 1)], vtN[EgtIf(vOrd[i] == 1, 1, 2)]) -- altrimenti è di fianco else vFaceUse2 = BL.GetNearestParalOpposite( vtN[EgtIf(vOrd[i] == 1, 2, 1)]) end EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse2) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) end else -- se con fresa di fianco if nUseMillOnSide > 0 then if bConvex then EgtSetMachiningParam( MCH_MP.FACEUSE, MCH_MILL_FU.PARAL_DOWN) if vtN[vOrd[i]]:getZ() >= 0 then if BD.DOWN_HEAD and nSide ~= 1 then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) end end else -- lascio lo stesso le lavorazioni anche se viene intercettato l'errore local vFaceUse2 = BL.GetNearestParalOpposite( vtN[EgtIf(vOrd[i] == 1, 2, 1)], vtN[EgtIf(vOrd[i] == 1, 1, 2)]) EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse2) if vtN[vOrd[i]]:getZ() < 0 then if BD.DOWN_HEAD and nSide ~= 1 then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, dEal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dSal) end end end else -- se faccia da sotto EgtSetMachiningParam( MCH_MP.FACEUSE, vFaceUse[vOrd[i]]) end end if bFacesSwapped then local dCurrStartAddLen = EgtGetMachiningParam( MCH_MP.STARTADDLEN) local dCurrEndAddLen = EgtGetMachiningParam( MCH_MP.ENDADDLEN) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dCurrEndAddLen) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dCurrStartAddLen) end -- imposto lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( bIsMachDownUp, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)) EgtSetMachiningParam( MCH_MP.INVERT, true) -- si aggiusta la direzione di lavoro in base a rotazione utensile e preferenza utente (nUseConventionalMilling da fuori o Q14) EgtMdbSetCurrMachining( sMilling) local bIsCurrentToolCCW = EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) < 0 if nUseConventionalMilling == nil then nUseConventionalMilling = EgtGetInfo( Proc.Id, 'Q14', 'd') or 0 end local bUseConventionalMilling = false if nUseConventionalMilling == 1 or ( nUseConventionalMilling == 2 and vtN[vOrd[i]]:getX() < 0.1 and Proc.AffectedFaces.Bottom) then bUseConventionalMilling = true end if bIsCurrentToolCCW ~= bUseConventionalMilling then local dCurrStartAddLen = EgtGetMachiningParam( MCH_MP.STARTADDLEN) local dCurrEndAddLen = EgtGetMachiningParam( MCH_MP.ENDADDLEN) local bCurrInvert = EgtGetMachiningParam( MCH_MP.INVERT) local nCurrWorkside = EgtGetMachiningParam( MCH_MP.WORKSIDE) EgtSetMachiningParam( MCH_MP.STARTADDLEN, dCurrEndAddLen) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dCurrStartAddLen) EgtSetMachiningParam( MCH_MP.INVERT, not bCurrInvert) EgtSetMachiningParam( MCH_MP.WORKSIDE, EgtIf( nCurrWorkside == MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)) end -- calcolo la componente dNz non in base alla classificazione della feature (sopra, sotto, fianchi) ma alla componente maggiore -- local dNz = EgtIf( nSide == 0, vtN[vOrd[i]]:getY(), vtN[vOrd[i]]:getZ()) -- local dNz = EgtIf( abs(vtN[vOrd[i]]:getY()) >= abs(vtN[vOrd[i]]:getZ()), vtN[vOrd[i]]:getY(), vtN[vOrd[i]]:getZ()) local dNz = EgtIf( abs(nSide) == 1, vtN[vOrd[i]]:getY(), vtN[vOrd[i]]:getZ()) local dNzMin = EgtIf( abs(vtN[vOrd[i]]:getY()) >= abs(vtN[vOrd[i]]:getZ()), vtN[vOrd[i]]:getY(), vtN[vOrd[i]]:getZ()) -- nel caso concavo, devo impostare la lunghezza di attacco ortogonale if not bConvex then local dLioPerp = EgtIf( i == 1, dFacElev1, dFacElev2) + BD.COLL_SIC EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp) end -- verifico massimo affondamento (tengo conto dell'inclinazione utensile e della pinza con estremità conica) -- 08/09/2020 tolti i 3mm ( per la ghiera smussata) perchè nella verifica collisione vine creato un cilindro non smussato che rileva la collisione -- local dCollSic = max( BD.COLL_SIC, ( dThDiam - dToolDiam) / 2 * abs( vtN[vOrd[i]]:getY() / vtN[vOrd[i]]:getZ()) - 3) -- local dCollSic = max( BD.COLL_SIC, ( dThDiam - dToolDiam) / 2 * EgtIf( abs(dNz) < GEO.EPS_SMALL, 1, abs( vtN[vOrd[i]]:getY() / dNz))) local dCollSic local dDepth -- assegno affondamento local dExtraElev = 0 -- se uso testa da sotto if bUseDownHead then dCollSic = max( BD.COLL_SIC, ( dThDiamDn - dToolDiamDn) / 2 * EgtIf( abs(dNz) < GEO.EPS_SMALL, 1, abs( EgtIf( abs(vtN[vOrd[i]]:getY()) >= abs(vtN[vOrd[i]]:getZ()), vtN[vOrd[i]]:getZ(), vtN[vOrd[i]]:getY()) / dNz))) if vWidth[vOrd[i]] + dAgg > dMaxDepthDn - dCollSic then sWarn = 'Warning in LongDoubleCut : depth (' .. EgtNumToString( vWidth[vOrd[i]] + dAgg, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepthDn - dCollSic, 1) .. ')' end dDepth = min( dMaxDepthDn - dCollSic, vWidth[vOrd[i]] + dAgg) EgtSetMachiningParam( MCH_MP.DEPTH, dDepth - dExtraElev) else dCollSic = max( BD.COLL_SIC, ( dThDiam - dToolDiam) / 2 * EgtIf( abs(dNz) < GEO.EPS_SMALL, 1, abs( EgtIf( abs(vtN[vOrd[i]]:getY()) >= abs(vtN[vOrd[i]]:getZ()), vtN[vOrd[i]]:getZ(), vtN[vOrd[i]]:getY()) / dNz))) if vWidth[vOrd[i]] + dAgg > dMaxDepth - dCollSic then sWarn = 'Warning in LongDoubleCut : depth (' .. EgtNumToString( vWidth[vOrd[i]] + dAgg, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth - dCollSic, 1) .. ')' end dDepth = min( dMaxDepth - dCollSic, vWidth[vOrd[i]] + dAgg) EgtSetMachiningParam( MCH_MP.DEPTH, dDepth - dExtraElev) end -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- se facce principali convesse, eventuale lavorazione della faccia limitante l'inizio (a destra) if bConvex and j == 1 and not bStartFixed and bRemoveToolRadius then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], 1, i, sMilling, dToolDiam) end -- se facce principali convesse, eventuale lavorazione della faccia limitante la fine (a sinistra) if bConvex and j == nC and not bEndFixed and bRemoveToolRadius then MakeSideFace( Proc.Id, tFaceLong[vOrd[i]], -1, i, sMilling, dToolDiam) end end end end return true, sWarn, nil, AddedIds end --------------------------------------------------------------------- return ProcessLong2Cut