-- ProcessLongCut.lua by Egaltech s.r.l. 2023/05/19 -- Gestione calcolo taglio longitudinale per Travi -- 2021/02/03 Corretto FaceUse con fresa orizzontale su taglio orizzontale. -- 2021/05/18 Possibile taglio con lama anche di fianco su macchina con testa da sotto. -- 2021/07/20 Possibile taglio con lama anche di fianco e da sotto su macchina con testa da sopra. -- 2021/07/20 Con utensile di fianco e con determinati angoli e se altezza utensile è inferiore all'altezza faccia -- è possibile fare doppio taglio opposto su tutte le facce(sopra, sotto e fianchi) -- 2021/09/03 Gestione facce lunghe non passanti con taglio di lama -- 2021/10/29 Aggiunta opzione tipo lavorazione 'LongCut'. -- 2021/11/04 Migliorata gestione sicurezza aggiuntiva in fresate di fianco (distinzione tra larga come tutta la faccia o meno). -- 2021/11/08 Se con lama e flag BD.USE_LONGCUT si lavora in direzione contraria allo standard. -- 2022/03/07 Razionalizzata gestione casi con fresa di fianco. Aggiunta gestione Long2Cut anche con testa sotto. -- 2022/07/14 Aggiunta limitazione lavorazione a sinistra anche se il grezzo successivo non ha lavorazioni (finale barra) ma è abbastanza lungo da poter essere riutilizzato (BD.MinRaw). -- 2022/09/23 Modificato l'angolo per l'abilitazione della lama da sotto: ora interviene anche per facce verticali. -- 2022/11/04 Aggiunto passaggio parametro bDownHead (Testa da Sotto) nelle chiamate a MakeSideFace. -- 2022/11/28 Correzioni varie per attacco, pulizia spigoli, utilizzo H3. -- 2022/11/30 Modifiche su SCC per TURN. -- 2023/01/18 Aggiunta, se richiesta, una lavorazione ulteriore con sega a catena nei casi in cui la doppia lama non sia sufficiente. -- 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/01/27 In caso di lavorazione aggiuntiva con fresa a catena il taglio con lama da sotto viene effettuato a step. -- 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/15 Modifica alla lavorazione ulteriore con sega a catena per togliere il codolo e lasciare solo dei punti di supporto. -- 2023/03/22 Correzione a SCC lama a seguito di modifiche alle direzioni dei tagli. -- 2023/04/17 Gestione unificata SCC tramite funzione apposita GetSCC -- 2023/05/03 Corretto SCC in caso di asse utensile allineato con Z. -- 2023/05/19 Migliorato calcolo e verifica affondamento per lavorazione con lama con codolo in mezzo. -- Tabella per definizione modulo local ProcessLongCut = {} -- Include require( 'EgtBase') local BL = require( 'BeamLib') local Fbs = require( 'FacesBySaw') EgtOutLog( ' ProcessLongCut started', 1) -- Dati local BD = require( 'BeamData') local ML = require( 'MachiningLib') local dLimMinPiece = BD.LEN_SHORT_PART or 1000 --------------------------------------------------------------------- -- Riconoscimento della feature function ProcessLongCut.Identify( Proc) return (( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 10) end --------------------------------------------------------------------- -- Classificazione della feature function ProcessLongCut.Classify( Proc) -- se una sola faccia non ci sono limiti if Proc.Fct == 1 then return true, false end -- verifico la normale della faccia principale local vtN = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT) if vtN:getZ() < - 0.5 then return true, true end return true, false end --------------------------------------------------------------------- -- Estrazione dell'UUID utensile di una lavorazione function GetToolUUID( sMachining) if EgtMdbSetCurrMachining( sMachining) then local sToolUUID = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) return sToolUUID end end --------------------------------------------------------------------- -- Calcolo dei versori caratteristici della feature function GetProcessSpecificVectors( Proc, nFacet, nFaceUse, bInvert, sMachining) local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacet, GDB_ID.ROOT) local vtOrthO = BL.GetVersRef( nFaceUse) local ptP1, ptPm, ptP2, vtV1, vtV2, dLen, dWidth = EgtSurfTmFacetOppositeSide( Proc.Id, nFacet, vtOrthO, GDB_ID.ROOT) local vtTg = ptP2 - ptP1 ; vtTg:normalize() local dAllStart = 0 local dAllEnd = 0 -- se bilinea, scarto la parte più allineata con la direzione ortogonale (se deviazione angolare oltre 20 deg o lunghezza minore di dSawDiam/2 * cos( 20/2)) ma maggiore di un minimo if ( ( ptPm - ptP1) - ( ptPm - ptP1) * vtTg * vtTg):len() > 100 * GEO.EPS_SMALL then local vtTg1 = ptPm - ptP1 ; vtTg1:normalize() local vtTg2 = ptP2 - ptPm ; vtTg2:normalize() local dDist1 = dist( ptP1, ptPm) local dDist2 = dist( ptP2, ptPm) local dCosMax = 0.951 -- cos( 18°) local dLenMin = 30 local dToolDiam = 400 if EgtMdbSetCurrMachining( sMachining) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dToolDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dToolDiam end end local dLenMax = max( 0.5 * dToolDiam * 0.17365 + 1, 2 * dLenMin) --if vtTg1 * vtTg2 < dCosMax or ( dDist1 < dLenMax and dDist1 > dLenMin) or ( dDist2 < dLenMax and dDist2 > dLenMin) then if vtTg1 * vtTg2 < dCosMax then local dOrtho1 = abs( vtTg1 * vtOrthO) local dOrtho2 = abs( vtTg2 * vtOrthO) if dOrtho1 < dOrtho2 or ( abs( dOrtho1 - dOrtho2) < 0.1 and dDist1 > 4 * dDist2) then if dDist1 > dLenMin or dDist1 > 0.5 * dDist2 then ptP2 = Point3d( ptPm) dAllEnd = - dDist2 - 10 * GEO.EPS_SMALL end else if dDist2 > dLenMin or dDist2 > 0.5 * dDist1 then ptP1 = Point3d( ptPm) dAllStart = - dDist1 - 10 * GEO.EPS_SMALL end end vtTg = ptP2 - ptP1 ; vtTg:normalize() end end local bWsRight = ( bInvert) -- Versore di riferimento local vtRef = Vector3d( vtTg) vtRef:rotate( vtN, 90) -- Versore esterno local vtOut = vtRef - vtRef * vtTg * vtTg ; vtOut:normalize() -- Versore ausiliario (direzione braccio) local vtAux = Vector3d( vtN:getX(), vtN:getY(), 0) ; vtAux:normalize() vtAux:rotate( Z_AX(), EgtIf( bWsRight, 90, -90)) if vtAux:isSmall() then vtAux = Vector3d( vtOut:getX(), vtOut:getY(), 0) ; vtAux:normalize() else if abs( vtAux * vtOut) < GEO.EPS_SMALL then if abs( vtTg:getZ()) > 0.5 then if vtAux * vtRef < 0 then vtAux = - vtAux end elseif vtAux * vtTg > 0 then vtAux = - vtAux end elseif vtAux * vtOut < 0 then vtAux = - vtAux end end EgtOutLog( 'vtN=' .. tostring( vtN) .. ' vtRef=' .. tostring( vtRef) .. ' vtOut=' .. tostring( vtOut) .. ' vtAux=' .. tostring( vtAux), 3) return vtAux, vtRef, vtOut, vtTg end --------------------------------------------------------------------- -- Calcolo posizione braccio function ProcessLongCut.GetSCC( Proc, nFacet, sMachining, nFaceUse, bInvert, nCuttingStep, nC, bAreCuttingStepsTowardsHead, bIsTopBlade, bCustUseBlade) local nSCC local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacet, GDB_ID.ROOT) local sToolUUID = GetToolUUID( sMachining) local bIsBlade if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sToolUUID) or '') then bIsBlade = ( ( EgtTdbGetCurrToolParam( MCH_TP.TYPE) & MCH_TF.SAWBLADE) ~= 0) end -- se Turn posiziono la testa per creare il minor ingombro possibile if BD.TURN then if nFaceUse == MCH_MILL_FU.ORTHO_DOWN or ( ( nFaceUse == MCH_MILL_FU.PARAL_FRONT or nFaceUse == MCH_MILL_FU.PARAL_BACK) and vtN:getZ() > -GEO.EPS_SMALL) then nSCC = MCH_SCC.ADIR_ZP elseif nFaceUse == MCH_MILL_FU.ORTHO_TOP or ( nFaceUse == MCH_MILL_FU.PARAL_FRONT or nFaceUse == MCH_MILL_FU.PARAL_BACK) then nSCC = MCH_SCC.ADIR_ZM elseif nFaceUse == MCH_MILL_FU.ORTHO_FRONT or ( ( nFaceUse == MCH_MILL_FU.PARAL_DOWN or nFaceUse == MCH_MILL_FU.PARAL_TOP) and vtN:getY() > -GEO.EPS_SMALL) then nSCC = MCH_SCC.ADIR_YP elseif nFaceUse == MCH_MILL_FU.ORTHO_BACK or ( nFaceUse == MCH_MILL_FU.PARAL_DOWN or nFaceUse == MCH_MILL_FU.PARAL_TOP) then nSCC = MCH_SCC.ADIR_YM end -- se Fast e fresa con asse utensile diretto come Z posiziono l'aggregato in Ym per avere il minore ingombro possibile elseif not BD.C_SIMM and not bIsBlade and AreSameVectorApprox( vtN, Z_AX()) then nSCC = MCH_SCC.ADIR_YM -- se Fast ( escluso caso speciale con taglio non passante e inclinato in X e escluso caso con lama esattamente diretta in Z) posiziono l'aggregato in X per ottimizzare il pinzaggio elseif not BD.C_SIMM and ( not ( bCustUseBlade and abs(vtN:getX()) > 0.001) or not bIsBlade) and not ( bIsBlade and AreSameVectorApprox( vtN, Z_AX())) then if bAreCuttingStepsTowardsHead then nSCC = EgtIf( ( not ( nCuttingStep == 1 or nCuttingStep == nC - 1)), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) else nSCC = EgtIf( ( not ( nCuttingStep == 1 or nCuttingStep == nC - 1)), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP) end -- per Fast ( caso speciale con taglio non passante e inclinato in X e caso lama diretta esattamente in Z) elseif not BD.C_SIMM then local vtAux = GetProcessSpecificVectors( Proc, nFacet, nFaceUse, bInvert, sMachining) if bCustUseBlade then nSCC = EgtIf( ( nFaceUse == MCH_MILL_FU.ORTHO_TOP or nFaceUse == MCH_MILL_FU.ORTHO_FRONT) and vtN:getY() > -GEO.EPS_SMALL, MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) elseif ( abs( vtAux:getX()) > abs( vtAux:getY()) - GEO.EPS_SMALL) then nSCC = EgtIf( ( vtAux:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM) else nSCC = EgtIf( ( vtAux:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) end -- per PF o simili e lama con aggregato lo posiziono per stare il più lontano possibile dalla trave elseif ( bIsBlade and bIsTopBlade) then if abs( vtN:getX()) > 0.001 then local vtAux = GetProcessSpecificVectors( Proc, nFacet, nFaceUse, bInvert, sMachining) nSCC = EgtIf( ( vtAux:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM) else nSCC = MCH_SCC.ADIR_XP end -- per PF o simili e lama senza aggregato o fresa non do alcuna preferenza else nSCC = MCH_SCC.NONE end return nSCC end ----------------------------------------------------------------------------------------------- local function MakeSideFace( nId, nFac, nSide, sMilling, dToolDiam, bForcedLim, dDistToMachine, bUnderDir) if ( not BD.DOWN_HEAD or not BD.TURN) and nSide == -1 then EgtOutLog( 'LongCut : side face finishing skipped , down head required') return true end -- inserisco la lavorazione local nM = 1 local nP = 1 local nFirstOverlap = 2 -- calcolo il numero di passata che devo fare per coprire l'impronta dells lama if dDistToMachine and abs(dDistToMachine) > 0 then nP = ceil( ( abs(dDistToMachine) + EgtIf( bForcedLim, 2 + nFirstOverlap, 2)) / ( dToolDiam - 2)) end for i = 1, nP do local sNameF = 'L2C_' .. ( EgtGetName( nId) or tostring( nId)) .. '_' .. tostring( nFac) .. '_' .. tostring( nM) 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}}) -- uso della faccia local nFaceUse if bForcedLim then nFaceUse = MCH_MILL_FU.ORTHO_LEFT -- lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.INVERT, false) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) else nFaceUse = EgtIf( bUnderDir, MCH_MILL_FU.PARAL_TOP, MCH_MILL_FU.PARAL_DOWN) if nSide == -2 then nFaceUse = MCH_MILL_FU.PARAL_BACK elseif nSide == 2 then nFaceUse = MCH_MILL_FU.PARAL_FRONT end -- lato di lavoro e inversione EgtSetMachiningParam( MCH_MP.INVERT, true) EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) end EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- modifico offset radiale if i < nP or i == 1 then EgtSetMachiningParam( MCH_MP.OFFSR, ((dToolDiam-2)*(i-1)) + EgtIf( bForcedLim, -nFirstOverlap, 0)) else local dPrevStep = (dToolDiam-2)*(i-2) EgtSetMachiningParam( MCH_MP.OFFSR, ( dDistToMachine + 2 - dToolDiam)) end -- attacco e uscita EgtSetMachiningParam( MCH_MP.LIPERP, 0) EgtSetMachiningParam( MCH_MP.LITANG, dToolDiam / 2 + 30) EgtSetMachiningParam( MCH_MP.LOPERP, 2) EgtSetMachiningParam( MCH_MP.LOTANG, 10) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end --------------------------------------------------------------------- local function MakeAntiSplintBySaw( Proc, nFacet, vtN, b3Raw, nFacInd, bReduceDepth, bMillDown, sMasterCutting) -- Recupero la lavorazione di lama o prendo quella passata local sCutting if sMasterCutting and #sMasterCutting > 0 then sCutting = sMasterCutting else sCutting = ML.FindCutting( 'HeadSide', not bMillDown, bMillDown) end if not sCutting then local sErr = 'Error : HeadSide (cutting) not found in library' EgtOutLog( sErr) return false, sErr end -- valuto l'angolo tra le due facce local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacet, GDB_ID.ROOT) local ptPm = (ptP1+ptP2)/2 -- ottengo il boundingBox e prendo le dimensioni lungo la normale (Z locale) che rappresenta l'elevazione della faccia -- laterale sul punto medio della linea in comune local frFc = Frame3d( ptPm, vtN) ; local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc) dDepth = b3BoxLoc:getDimZ() or 0 -- recupero i dati dell'utensile local dSawDiam = 400 local dSawThick = 0 local dMaxDepth = 0 if EgtMdbSetCurrMachining( sCutting) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dSawDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiam dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth end end local dExtraOffs = 0 -- se profondità superiore al massimo lama modifico elevazione if dDepth > dMaxDepth then dExtraOffs = dMaxDepth - dDepth end -- se devo ridurre l'affondamento if bReduceDepth then local dLimitDepth = 100 -- se ho ridotto l'affondamento ne riduco ulteriormente l'affondamento (50mm) if abs(dExtraOffs) > 0 then if dMaxDepth > dLimitDepth then dExtraOffs = dLimitDepth - dDepth end else if dDepth > dLimitDepth then dExtraOffs = dLimitDepth - dDepth else dExtraOffs = - (dDepth/2) end end end -- eseguo il taglio local bMadeASbyBld, sWarn, nIdMach = Fbs.MakeOne( Proc.Id, nFacet, sCutting, dSawDiam, vtN, nil, ( -0.5 + dExtraOffs), BD.CUT_SIC, 0, 0, 0, nil, b3Raw) if bMadeASbyBld then sWarn = nil if abs(dExtraOffs) > 0 then sWarn = 'Warning : antisplint elevation is bigger than max tool depth' end end return bMadeASbyBld, sWarn, nIdMach, dSawThick, dMaxDepth, bAdj, dAng, dExtraOffs end --------------------------------------------------------------------- local function ManageAntiSplintBySaw( Proc, b3Raw, bIsU, vtN, nFacet, nFacInd, sWarn, bMillDown, bReduceDepth, sCutting) local bMadeASbyBld = false local nNumFac = EgtIf( bIsU, 2, 1) local nPrefSide = 1 -- di preferenza il motore è meglio tenerlo sinistra -- se a U cerco di ottimizzare il lato di lavoro della lama if bIsU then if abs( vtN:getY()) > 0.996 then nPrefSide = 0 elseif abs( vtN:getZ()) > 0.63 or abs( vtN:getY()) > 0.63 then -- se X è negativa allora devo tenere il motore a destra if vtN:getX() < -(10 * GEO.EPS_SMALL) then nPrefSide = 2 end end end -- va eseguito sulle facce diverse dalla principale local nPrevSCC = nil for nFacet = 0, nNumFac do if nFacet ~= nFacInd then -- lavoro local dSawThick = 0 local dMaxDepth = 200 local bAdj, dAng, dExtraOffs, sWarn2, nIdMach bMadeASbyBld, sWarn2, nIdMach, dSawThick, dMaxDepth, bAdj, dAng, dExtraOffs = MakeAntiSplintBySaw( Proc, nFacet, vtN, b3Raw, nFacInd, bReduceDepth, bMillDown, sCutting) if not bMadeASbyBld then return bMadeASbyBld, false, sWarn2 end if sWarn2 then if not sWarn then sWarn = '' end sWarn = EgtIf( #sWarn > 0, sWarn .. '\n' .. sWarn2, sWarn2) end -- se antischeggia veramente inserito perchè necessario if nIdMach then -- verifico se da invertire local bInvertMach = false local dDepth = 0 if bIsU then if abs(vtN:getZ()) > 0.63 or abs(vtN:getY()) > 0.63 then -- if abs(vtN:getZ()) > 0.7 or abs(vtN:getY()) > 0.7 then -- prendo il vettore normale alla faccia local _, vtNFc = EgtSurfTmFacetCenter( Proc.Id, nFacet, GDB_ID.ROOT) -- se superficie principale parallela al piano XZ if nPrefSide == 0 then -- se facce inclinate \\ allora mandrino a destra (per essere verso l'alto) if vtNFc:getX() * vtNFc:getZ() > 0 then nPrefSide = 2 -- altrimenti facce inclinate // quindi mandrino a sinistra (per essere ancora verso l'alto) else nPrefSide = 1 end end -- se faccia verso X+ e mandrino verso sinistra if vtNFc:getX() > 0 and nPrefSide == 1 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end -- se faccia verso X- e mandrino verso destra elseif vtNFc:getX() < 0 and nPrefSide == 2 then -- se angolo interno e circa -90 if abs( dAng + 90) < 5 then bInvertMach = true end end end end -- eseguo inversione if bInvertMach then local bToolInvert = EgtGetMachiningParam( MCH_MP.TOOLINVERT) local nWS = EgtGetMachiningParam( MCH_MP.WORKSIDE) local nInvWS = EgtIf( nWS == MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT) local nFaceUse = EgtGetMachiningParam( MCH_MP.FACEUSE) local bOrtUp = ( nFaceUse >= MCH_MILL_FU.ORTUP_DOWN and nFaceUse <= MCH_MILL_FU.ORTUP_RIGHT) if not bOrtUp then -- assegno i parametri invertiti EgtSetMachiningParam( MCH_MP.WORKSIDE, nInvWS) EgtSetMachiningParam( MCH_MP.TOOLINVERT, not bToolInvert) -- setto l'offset pari allo spessore lama EgtSetMachiningParam( MCH_MP.OFFSL, -dSawThick) end end -- posizione del braccio : se primo taglio la recupero, altrimenti la imposto if not nPrevSCC then nPrevSCC = EgtGetMachiningParam( MCH_MP.SCC) else EgtSetMachiningParam( MCH_MP.SCC, nPrevSCC) end -- rieseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nIdMach, false) return false, false, sErr end end end end return bMadeASbyBld, true, sWarn end --------------------------------------------------------------------- -- Applicazione della lavorazione local function MakeByPocketing( Proc, nPhase, nRawId, nPartId) -- recupero la faccia con il maggior numero di adiacenze e l'elevazione relativa local nFacInd, dFacElev = BL.GetFaceWithMostAdj( Proc.Id, nPartId) -- cerco la svuotatura opportuna local sPocketing = ML.FindPocketing( 'OpenPocket', Proc.Box:getDimX()) 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, 0}}) -- 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 sNotes = 'MaxElev=' .. EgtNumToString( dFacElev, 1) .. ';' sNotes = sNotes .. 'VMRS=0;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) -- eseguo if not ML.ApplyMachining( true, false) then -- provo ad allargare leggermente la tasca EgtSetMachiningParam( MCH_MP.OFFSR, -0.1) if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end return true, sWarn end --------------------------------------------------------------------- -- lavorazione faccia laterale con sega a catena local function MakeSideFaceByChainSaw( nSurfId, dDepth, dOffs, dSal, dEal, bShortenStart, bShortenEnd) -- Recupero i dati dell'utensile local sSawing = ML.FindSawing( 'Sawing') local dMaxMat = 0 local dSawCornerRad = 0 local dSawThick = 0 local dSawDiameter = 0 -- se non trova una lavorazione di sawing esco if not sSawing then local sErr = 'Error : Sawing not found in library' EgtOutLog( sErr) return false, sErr else if EgtMdbSetCurrMachining( sSawing) then local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or dMaxMat dSawThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dSawThick dSawCornerRad = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) or dSawCornerRad dSawDiameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or dSawDiameter end end end -- inserisco la lavorazione di sawing local sName = 'Csaw_' .. ( EgtGetName( nSurfId) or tostring( nSurfId)) .. '_1' 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( {{ nSurfId, 0}}) -- imposto faceuse local nFaceUse = MCH_MILL_FU.PARAL_DOWN EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetChainSawBlockedAxis( 1)) local vtN = EgtSurfTmFacetNormVersor( nSurfId, 0, GDB_ID.ROOT) local vtOrtho = BL.GetVersRef( nFaceUse) EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtN, vtOrtho, 1)) -- imposto eventuale sovramateriale EgtSetMachiningParam( MCH_MP.OFFSR, dOffs) -- imposto tratti in cui la sega a catena non lavora per lasciare del materiale di supporto local dSupportingWoodLength = 30 -- imposto allungamento percorso iniziale e finale if bShortenStart then EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal - dSupportingWoodLength - dSawDiameter) else EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) end if bShortenEnd then EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal - dSupportingWoodLength - dSawDiameter) else EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) end -- imposto il lato di lavorazione local nWorkSide = MCH_MILL_WS.RIGHT EgtSetMachiningParam( MCH_MP.WORKSIDE, nWorkSide) -- verifico se devo ridurre l'affondamento if dMaxMat >= dDepth then EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) else EgtSetMachiningParam( MCH_MP.DEPTH, dMaxMat) sWarn = 'Warning : chainsaw elevation bigger than max tool depth' EgtOutLog( sWarn) end -- eseguo if not ML.ApplyMachining( true, false) then if EgtGetOutstrokeInfo() then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end -- impostazione alternativa angolo 3° asse rot EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetChainSawBlockedAxis( 2)) EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( vtN, vtOrtho, 2)) if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end if EgtIsMachiningEmpty() then _, sWarn = EgtGetMachMgrWarning( 0) EgtSetOperationMode( nMchFId, false) return false, sWarn end --end return true, sWarn end --------------------------------------------------------------------- -- Applicazione della lavorazione function ProcessLongCut.Make( Proc, nPhase, nRawId, nPartId, bCustUseBlade, nCustForceUseBladeOnNCF) -- recupero l'ingombro del grezzo di appartenenza local b3Raw = EgtGetRawPartBBox( nRawId) local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) -- dati della faccia local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, 0, GDB_ID.ROOT) local _, dLen, dWidth = EgtSurfTmFacetMinAreaRectangle( Proc.Id, 0, GDB_ID.ROOT) -- limitazioni su inizio e fine derivanti da altre facce local bLimXmin = false local bLimXmax = false if Proc.Fct >= 3 then bLimXmin = true bLimXmax = true elseif Proc.Fct >= 2 then local ptC1, vtN1 = EgtSurfTmFacetCenter( Proc.Id, 1, GDB_ID.ROOT) if vtN1:getX() > 0 then bLimXmin = true else bLimXmax = true end end -- Verifico lato di lavorazione (limite di lato a 45deg per FAST e 36deg per PF) local nSide = 1 if vtN:getZ() < - 0.5 then nSide = -1 elseif vtN:getY() < - EgtIf( BD.C_SIMM, 0.588, 0.7072) then nSide = -2 elseif vtN:getY() > EgtIf( BD.C_SIMM, 0.588, 0.7072) then nSide = 2 end -- Verifico se largo come faccia local bLarghAsFace = false if nSide == 1 or nSide == -1 then bLarghAsFace = ( Proc.Box:getDimY() > b3Solid:getDimY() - 20) else bLarghAsFace = ( Proc.Box:getDimZ() > b3Solid:getDimZ() - 20) end -- Determino se parte da sopra local bTopStart = ( Proc.Box:getMax():getZ() > b3Solid:getMax():getZ() - 20) -- Determino se parte da sotto local bBottomStart = ( Proc.Box:getMin():getZ() < b3Solid:getMin():getZ() + 20) -- Determino se lavorazione da davanti o da dietro local bFront = ( vtN:getY() < 0) -- Ottengo la distanza tra la fine del pezzo e il pezzo successivo o grezzo utilizzabile e non ancora separato local dDistToNextPiece = BL.GetDistanceToNextPart( nRawId, nPhase) local bForcedLim local sWarn ---------------------------------------------------------------------------------------------------------------------------------------- -- 2020/09/15 Fabio Squaratti: se sono attivi entrambe i Q05 (lavorare con lama) e Q07 (lavorare con fresa di fianco anche da sopra) -- allora vince il Q7, 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 terminali, l'utensile deve arrivare -- fino al punto più vicino della faccia terminale (prima l'arretramento era sempre del raggio utensile). -- Questo viene fatto se Q07=1 o fresa da sotto ---------------------------------------------------------------------------------------------------------------------------------------- local nUseBlade = 0 if bCustUseBlade then nUseBlade = 1 -- leggo il parametro Q05 solo se è una vera longcut L010 elseif ProcessLongCut.Identify( Proc) then nUseBlade = EgtGetInfo( Proc.Id, 'Q05', 'i') or 0 end local bForceUseBladeOnNotThruFace if nCustForceUseBladeOnNCF then bForceUseBladeOnNotThruFace = nCustForceUseBladeOnNCF > 2 nUseBlade = EgtIf( nCustForceUseBladeOnNCF > 2, nCustForceUseBladeOnNCF-2, nCustForceUseBladeOnNCF) else -- bForceUseBladeOnNotThruFace = EgtGetInfo( Proc.Id, 'Q06', 'b') or false -- non viene più usato un nuovo Q (Q06) ma dipende dal valore del Q05 -- con nuovi valori 3: come 1 ma con forza lama su facce chiuse; 4: come 2 ma con forza lama su facce chiuse if nUseBlade > 2 then nUseBlade = nUseBlade - 2 bForceUseBladeOnNotThruFace = true end end -- se ho il parametro settato dal LapJoint (per ora è questo componente che setta questo parametro) allora setto a false l'uso della lama -- perchè se ha questo parametro a true significa che la lama è forzata ad essere usata local nUseMillOnSide if nCustForceUseBladeOnNCF then nUseMillOnSide = 0 else nUseMillOnSide = EgtGetInfo( Proc.Id, 'Q07', 'i') or 0 end -- se entrambe i Q sono attivi, disabilito lama if nUseMillOnSide > 0 then nUseBlade = 0 bForceUseBladeOnNotThruFace = false end local bCanUseBlade = false local bCanUseUnderBlade = false -- se lama abilitata per lavorare sopra e faccia da sopra if nUseBlade == 1 and nSide == 1 then bCanUseBlade = true end -- se lama abilitata per lavorare anche i fianchi e da sotto e non c'è testa da sotto if nUseBlade == 2 and not BD.DOWN_HEAD then if ( nSide == 1 or abs(nSide) == 2) and vtN:getZ() >= -0.0175 then bCanUseBlade = true end end -- se lama abilitata per lavorare i fianchi e da sotto e c'è testa da sotto if nUseBlade == 2 and BD.DOWN_HEAD then -- se faccia da sotto o di lato ma con versore Z negativo che supera i 30° da Z- if ( nSide == -1 or abs(nSide) == 2) and vtN:getZ() <= -0.5 then bCanUseUnderBlade = true end -- se faccia da sotto o di lato ma con versore Z sotto l'orizzontale abilito la lavorazione con lame mixate if ( nSide == -1 or abs(nSide) == 2) and vtN: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 (28deg) per non avere extracorsa if ( nSide == 1 or abs(nSide) == 2) and vtN:getZ() >= -0.4695 then bCanUseBlade = true end end -- introduco messaggi di errore in caso sia settata la lama ma impossibile utilizzarla -- se si toglie questa parte il processo continua utilizzandi però la fresa ma per il vincolo del parametro Q non è possibile if nUseBlade == 2 and not BD.DOWN_HEAD and not bCanUseBlade then local sErr = 'Error, impossible use blade on negative side face' EgtOutLog( sErr) return false, sErr elseif nUseBlade == 1 and not bCanUseBlade then local sErr = 'Error, impossible use blade' EgtOutLog( sErr) return false, sErr elseif nUseBlade == 2 and BD.DOWN_HEAD and not bCanUseBlade and not bCanUseUnderBlade then local sErr = 'Error, impossible use blade' EgtOutLog( sErr) return false, sErr end -- Se non limitato o forzato uso lama e da sopra e richiesto con doppio taglio di lama e superiore al limite minimo if ( ( not bLimXmin and not bLimXmax) or bForceUseBladeOnNotThruFace) and ( bCanUseUnderBlade or bCanUseBlade) and nUseBlade > 0 and b3Solid:getDimX() > dLimMinPiece - 1 then local sCutting local dToolDiam = 0 local dThick = 0 local dMaxDepth = 0 local dMaxVertDepth = 0 local sCuttingDn local dToolDiamDn = 0 local dThickDn = 0 local dMaxDepthDn = 0 -- recupero eventuale lavorazione con lama su testa da sotto if bCanUseUnderBlade then sCuttingDn = ML.FindCutting( 'HeadSide_H2', false, true) if not sCuttingDn then local sErr = 'Error : sawing HeadSide_H2 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 dThickDn = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dThickDn dMaxDepthDn = EgtTdbGetCurrToolMaxDepth() or dMaxDepthDn end end end -- recupero eventuale lavorazione con lama 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 dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) or dThick dMaxDepth = EgtTdbGetCurrToolMaxDepth() or dMaxDepth dMaxVertDepth = dMaxDepth - ( BD.DECR_VERT_CUT or 0) 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 not bLimXmin then if bForceUseBladeOnNotThruFace then bForcedLim = true bLimXmin = true else sWarn = 'Warning on saw cut : Cut machining can damage next piece' EgtOutLog( sWarn) end end -- disabilitato la selezione del codolo, prende sempre quello più piccolo. Non cancellare quello disabiliato in caso di ripristino local dDimStrip = BD.DIM_STRIP_SMALL * EgtIf( nSide == -1, -1, 1) -- determino gli estremi local bStartFixed local bEndFixed local dStartAccDist local dStartDist local dEndAccDist local dEndDist local dStartAccDistUp = BD.LONGCUT_ENDLEN local dStartDistUp = 0 local dEndAccDistUp = BD.LONGCUT_ENDLEN local dEndDistUp = 0 local dStartAccDistDn = BD.LONGCUT_ENDLEN local dStartDistDn = 0 local dEndAccDistDn = BD.LONGCUT_ENDLEN local dEndDistDn = 0 if bForceUseBladeOnNotThruFace then if bCanUseBlade then bStartFixed = true if bLimXmax then local dRadius = dToolDiam / 2 local dCat1 = dRadius - ( ( dWidth - dDimStrip) / 2) dStartDistUp = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) dStartAccDistUp = BD.LONGCUT_MAXLEN bStartFixed = false end bEndFixed = true if bLimXmin then local dRadius = dToolDiam / 2 local dCat1 = dRadius - ( ( dWidth - dDimStrip) / 2) dEndDistUp = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) dEndAccDistUp = BD.LONGCUT_MAXLEN bEndFixed = false end end if bCanUseUnderBlade then bStartFixed = true if bLimXmax then local dRadius = dToolDiamDn / 2 local dCat1 = dRadius - ( ( dWidth - dDimStrip) / 2) dStartDistDn = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) dStartAccDistDn = BD.LONGCUT_MAXLEN bStartFixed = false end bEndFixed = true if bLimXmin then local dRadius = dToolDiamDn / 2 local dCat1 = dRadius - ( ( dWidth - dDimStrip) / 2) dEndDistDn = sqrt( ( dRadius * dRadius) - (dCat1 * dCat1)) dEndAccDistDn = BD.LONGCUT_MAXLEN bEndFixed = false end end end 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 ( dato dal diametro utensile più grande) if nCUp then nC = nCUp dC = dCUp elseif nCDn then nC = nCDn dC = dCDn end -- nei casi in cui la doppia lama non sia sufficiente, se richiesto, attivo un'ulteriore lavorazione con sega a catena -- solo per T010 local bFinishWithChainSaw = false if ( Proc.Prc == 10 and not ProcessLongCut.Identify( Proc)) and bLarghAsFace and abs( nSide) == 2 and ( bCanUseBlade and bCanUseUnderBlade) and Proc.Fct == 1 then bFinishWithChainSaw = EgtIf ( ( EgtGetInfo( Proc.Id, 'Q05', 'i') or 0) == 1, true, false) 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:getY()) > 0.01, MCH_MILL_FU.ORTHO_TOP, EgtIf( bFront, MCH_MILL_FU.ORTHO_FRONT, MCH_MILL_FU.ORTHO_BACK)) nFaceUse2 = EgtIf( abs( vtN: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:getY()) > 0.01, MCH_MILL_FU.ORTHO_TOP, EgtIf( bFront, MCH_MILL_FU.ORTHO_BACK, MCH_MILL_FU.ORTHO_FRONT)) nFaceUse2 = EgtIf( abs( vtN:getY()) > 0.01, MCH_MILL_FU.ORTHO_DOWN, EgtIf( bFront, MCH_MILL_FU.ORTHO_FRONT, MCH_MILL_FU.ORTHO_BACK)) end -- si percorrono i lati alto e basso della faccia -- calcolo quanto è l'affondamento del taglio local dMainMaxDepth = EgtIf( abs( vtN:getY()) < 1e-6, dMaxDepth, dMaxVertDepth) local dOtherMaxDept = EgtIf( bCanUseUnderBlade, dMaxDepthDn, dMainMaxDepth) local dCoeff = min( ( dWidth - dDimStrip) / ( dMainMaxDepth + dOtherMaxDept), 1) local dOffsetTopBlade = dWidth - dCoeff * dMainMaxDepth local dOffsetDownBlade = dWidth - dCoeff * dOtherMaxDept local nStepDownBlade = 1 local dStepDownBlade = dOtherMaxDept -- se lama da sotto verifico se la componente Y della profondità di taglio supera la capacità della lama if ( nSide == -1 or abs(nSide) == 2) and bCanUseUnderBlade and ( dOffsetTopBlade - dDimStrip) > dOtherMaxDept then if bFinishWithChainSaw then local dHCutDownBlade = dWidth - dOffsetDownBlade local dMaxStepDownBlade = 80 nStepDownBlade = ceil( dHCutDownBlade / dMaxStepDownBlade) dStepDownBlade = dHCutDownBlade / nStepDownBlade else local dDelta = dWidth - dDimStrip - ( dMainMaxDepth + dOtherMaxDept) local sErr = 'Error : side depth is bigger than total cut depth (Diff=' .. EgtNumToString( dDelta)..')' EgtOutLog( sErr) return false, sErr end else bFinishWithChainSaw = false end local nM = 0 -- se abilitata la lavorazione di lama su faccia chiusa, aggiungo le eventuali lavorazioni di antischeggia -- e di asporto dell'impronta lama if bForceUseBladeOnNotThruFace and ( bLimXmin or bLimXmax) then local nCountMilHead = 0 -- determino la massima elevazione local dElev = BL.GetFaceElevation( Proc.Id, 0, nPartId) -- recupero la lavorazione local sMilling = ML.FindMilling( 'Long2Cut_H2', dElev, nil, nil, nil, not bCanUseUnderBlade, bCanUseUnderBlade) if not sMilling then local sErr = 'Error : milling Long2Cut (_H2) 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 -- se ho facce di chiusura, per prima cosa faccio antischeggia -- come richiesto da Fabio Squaratti il 03/09/2021 if ( bLimXmin and not bForcedLim) or bLimXmax then local bOk, nFacet bMadeASbyBld, bOk, sWarn = ManageAntiSplintBySaw( Proc, b3Raw, (( bLimXmin and not bForcedLim) and bLimXmax), vtN, nFacet, 0, sWarn, bCanUseUnderBlade, nil, sCutting) if not bOk then return false, sWarn end end -- eventuale lavorazione della faccia limitante l'inizio if not bStartFixed then local vtIni = -X_AX() for j = 1, Proc.Fct - 1 do local _, vtN = EgtSurfTmFacetCenter( Proc.Id, j, GDB_ID.ROOT) if vtIni * vtN > 0 and nCountMilHead < 2 then MakeSideFace( Proc.Id, j, nSide, sMilling, dToolDiam, nil, max(dStartDistUp,dStartDistDn), bCanUseUnderBlade) nCountMilHead = nCountMilHead + 1 end end if bForcedLim and nCountMilHead < 1 then MakeSideFace( Proc.Id, 0, nSide, sMilling, dToolDiam, bForcedLim, max(dStartDistUp,dStartDistDn), bCanUseUnderBlade) nCountMilHead = nCountMilHead + 1 end end -- eventuale lavorazione della faccia limitante la fine if not bEndFixed then local vtFin = X_AX() for j = 1, Proc.Fct - 1 do local _, vtN = EgtSurfTmFacetCenter( Proc.Id, j, GDB_ID.ROOT) if vtFin * vtN > 0 and nCountMilHead < 2 then MakeSideFace( Proc.Id, j, nSide, sMilling, dToolDiam, nil, max(dEndDistUp,dEndDistDn), bCanUseUnderBlade) nCountMilHead = nCountMilHead + 1 end end if bForcedLim and nCountMilHead < 2 then MakeSideFace( Proc.Id, 0, nSide, sMilling, dToolDiam, bForcedLim, max(dEndDistUp,dEndDistDn), bCanUseUnderBlade) nCountMilHead = nCountMilHead + 1 end end end -- inserisco tagli di lama for i = 1, nC do -- ciclo sulle passate local dLioTang = 0 for k = 1, 2 do local nStep = 1 if k == 2 then nStep = nStepDownBlade end for Zstep = nStep, 1, -1 do local dLioPerp = ( dWidth - dDimStrip) / 2 + BD.CUT_SIC local bAddOpposite = true local dAddExtraPerp = 0 -- se faccia da sotto e angolo inferiore ai 12° o faccia di fianco e angolo inferiore a 15° (al di sotto di questo angolo -- l'attacco lama si comporta in modo diverso) allora calcolo il valore perpendicolare con la funzione CalcLeadInOutPerpGeom if ( nSide == -1 and abs(vtN:getY()) >= 0.2079) or ( abs(nSide) == 2 and abs(vtN:getZ()) >= 0.2588) then bAddOpposite = false end -- faccio in modo di calcolare il valore perpendicolare solo sulla faccia da sotto nel secondo passo o sulla faccia di fianco nel primo passo if nSide == 1 or ( nSide == -1 and k == 1) or ( abs(nSide) == 2 and k == 2) then bAddOpposite = false end if bAddOpposite then -- controllo se devo aggiungere un extra all'attacco perpendicolare if nSide == -1 then if vtN:getY() > 0 then dAddExtraPerp = Proc.Box:getMin():getY() - b3Solid:getMin():getY() elseif vtN:getY() < 0 then dAddExtraPerp = b3Solid:getMax():getY() - Proc.Box:getMax():getY() end elseif abs(nSide) == 2 then dAddExtraPerp = Proc.Box:getMin():getZ() - b3Solid:getMin():getZ() end dLioPerp = dLioPerp + dAddExtraPerp end -- inserisco le parti di lavorazione nM = nM + 1 local sNameF local nMchFId if ( k == 1 and bCanUseBlade) or ( k == 2 and ( bCanUseBlade and not bCanUseUnderBlade)) then sNameF = 'L2C_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. 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 dEndDist = dEndDistUp dEndAccDist = dEndAccDistUp dStartDist = dStartDistUp dStartAccDist = dStartAccDistUp elseif ( k == 2 and bCanUseUnderBlade) or ( k == 1 and ( bCanUseUnderBlade and not bCanUseBlade)) then sNameF = 'L2CD_' .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. 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 dEndDist = dEndDistDn dEndAccDist = dEndAccDistDn dStartDist = dStartDistDn dStartAccDist = dStartAccDistDn end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, 0}}) -- 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 local nFaceUseCurrent if bCanUseBlade and bCanUseUnderBlade then dSal, dEal = dEal, dSal if k == 1 then bIsTopBladeCurrent = true nFaceUseCurrent = nFaceUse2 else bIsTopBladeCurrent = false nFaceUseCurrent = nFaceUse end elseif bCanUseUnderBlade then if k == 1 then bIsTopBladeCurrent = false nFaceUseCurrent = nFaceUse else bIsTopBladeCurrent = false nFaceUseCurrent = nFaceUse2 end else if k == 1 then bIsTopBladeCurrent = true nFaceUseCurrent = nFaceUse else bIsTopBladeCurrent = true nFaceUseCurrent = nFaceUse2 end end -- recupero alcune informazioni utili dalla lavorazione attuale local bIsCurrentBladeCCW if bIsTopBladeCurrent then EgtMdbSetCurrMachining( sCutting) else EgtMdbSetCurrMachining( sCuttingDn) end 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) ~= 2 then if bIsCurrentBladeCCW then nWorkSide = MCH_MILL_WS.LEFT bInvert = true dSal, dEal = dEal, dSal else nWorkSide = MCH_MILL_WS.RIGHT bInvert = false end else if bIsCurrentBladeCCW then nWorkSide = MCH_MILL_WS.LEFT bInvert = false else nWorkSide = MCH_MILL_WS.RIGHT bInvert = true dSal, dEal = dEal, dSal end end -- step sempre positivi local bAreCuttingStepsTowardsHead = true -- calcolo SCC local nSCC = ProcessLongCut.GetSCC( Proc, 0, EgtIf( bIsTopBladeCurrent, sCutting, sCuttingDn), nFaceUseCurrent, bInvert, i, nC, bAreCuttingStepsTowardsHead, bIsTopBladeCurrent, bCustUseBlade) -- 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 local dOffset = EgtIf( k == 1, dOffsetTopBlade, dOffsetDownBlade + dStepDownBlade * ( Zstep - 1)) 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 EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end end end -- se richiesto aggiungo la lavorazione con sega a catena if bFinishWithChainSaw then local dChainSawOverMaterial = 0 local dChainSawDepth = dOffsetDownBlade + BD.CUT_EXTRA dEndDist = dEndDistUp dEndAccDist = dEndAccDistUp dStartDist = dStartDistUp dStartAccDist = dStartAccDistUp for i = nC, 1, -1 do local bFirstCut = ( i == nC) local bLastCut = ( i == 1) local dSal = EgtIf( bFirstCut, -dEndDist, - dEndAccDist - ( nC - i - 1) * dC) local dEal = EgtIf( bLastCut, -dStartDist, - dStartAccDist - ( i - 2) * dC) local bShortenStartOrEnd = true local bChainSawOk, sErr = MakeSideFaceByChainSaw( Proc.Id, dChainSawDepth, dChainSawOverMaterial, dSal, dEal, bShortenStartOrEnd, bShortenStartOrEnd) if not bChainSawOk then return false, sErr end end end -- se non è sotto e non uso fresa di fianco: lavorazione Long2Cut elseif ( nSide ~= - 1 or BD.DOWN_HEAD) and nUseMillOnSide == 0 then -- determino la massima elevazione local dElev = BL.GetFaceElevation( Proc.Id, 0, nPartId) -- recupero la lavorazione local bDownHead = ( nSide == - 1) sMchType = EgtIf( bDownHead, 'Long2Cut_H2', 'Long2Cut') -- rimossa l'esclusione della terza testa a seguito di modifica della testa stessa che la rende utilizzabile in tutti i casi --local bExcludeH3 = bLarghAsFace and abs( nSide) ~= 1 local sMilling = ML.FindMilling( sMchType, dElev, nil, nil, nil, not bDownHead, bDownHead, nil, bExcludeH3) if not sMilling then local sErr = 'Error : milling '..sMchType..' 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 -- 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 dDistToNextPiece < dToolDiam/2 and not bLimXmin then bForcedLim = true bLimXmin = true end -- se chiuso e corto, applico svuotatura con fresa opportuna if bLimXmin and bLimXmax and Proc.Box:getDimX() < 2 * dToolDiam then return MakeByPocketing( Proc, nPhase, nRawId, nPartId) end -- determino l'utilizzo della faccia local nFaceUse = EgtIf( abs( vtN:getY()) > 0.01, MCH_MILL_FU.ORTHO_DOWN, EgtIf( bFront, MCH_MILL_FU.ORTHO_FRONT, MCH_MILL_FU.ORTHO_BACK)) -- determino il lato di attacco (0:xMin, 1:xMax) local nStartSide = 0 if nFaceUse == MCH_MILL_FU.ORTHO_DOWN and not bFront then nStartSide = 1 elseif nFaceUse ~= MCH_MILL_FU.ORTHO_DOWN then if ( bFront and nSide == -1) or ( not bFront and nSide == 1) then nStartSide = 1 end end -- determino gli estremi local dStartDist = 0 local dStartAccDist = BD.LONGCUT_ENDLEN local bStartFixed = true if ( bLimXmin and nStartSide == 0) or ( bLimXmax and nStartSide == 1) then dStartDist = dToolDiam / 2 dStartAccDist = BD.LONGCUT_MAXLEN bStartFixed = false end local dEndDist = 0 local dEndAccDist = BD.LONGCUT_ENDLEN local bEndFixed = true if ( bLimXmin and nStartSide == 1) or ( bLimXmax and nStartSide == 0) then dEndDist = dToolDiam / 2 dEndAccDist = BD.LONGCUT_MAXLEN bEndFixed = false end -- determino 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 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 -- si percorre il lato basso della faccia local nM = 0 local nCountMilHead = 0 for i = 1, nC do -- ciclo sulle passate local nO = 1 local dStep = 0 if dWidth + 2 * BD.CUT_EXTRA > 0.8 * dToolDiam then nO = ceil(( dWidth + 2 * BD.CUT_EXTRA) / ( 0.6 * dToolDiam)) if nO > 1 then dStep = ( dWidth + 2 * BD.CUT_EXTRA) / nO end end for k = nO, 1, -1 do -- inserisco le parti di lavorazione nM = nM + 1 local sNameF = 'L2CH_' .. ( 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 -- correggo l'attacco se necessario if i == 1 and not bStartFixed then if nO == 1 or EgtGetMachiningParam( MCH_MP.LITANG) ~= 0 then EgtSetMachiningParam( MCH_MP.LIELEV, 0) EgtSetMachiningParam( MCH_MP.LITANG, 0) EgtSetMachiningParam( MCH_MP.LEADINTYPE, MCH_MILL_LI.LINEAR) EgtSetMachiningParam( MCH_MP.LIPERP, dWidth + BD.CUT_EXTRA + ( BD.CUT_SIC or 20)) end elseif i == nC and not bEndFixed then if nO == 1 or EgtGetMachiningParam( MCH_MP.LOTANG) ~= 0 then EgtSetMachiningParam( MCH_MP.LOELEV, 0) EgtSetMachiningParam( MCH_MP.LOTANG, 0) EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, MCH_MILL_LI.LINEAR) EgtSetMachiningParam( MCH_MP.LOPERP, dWidth + BD.CUT_EXTRA + ( BD.CUT_SIC or 20)) end end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, 0}}) -- setto workside e eventuale inversione local bInvert if bInvert then EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.RIGHT) EgtSetMachiningParam( MCH_MP.INVERT, true) else EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) EgtSetMachiningParam( MCH_MP.INVERT, false) end -- limito opportunamente la lavorazione local dSal = EgtIf( i == 1, -dStartDist, - dStartAccDist - ( i - 2) * dC) local dEal = EgtIf( i == nC, -dEndDist, - dEndAccDist - ( nC - i - 1) * dC) if bInvert then dSal, dEal = dEal, dSal end EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- imposto offset radiale EgtSetMachiningParam( MCH_MP.OFFSR, ( k - 1) * dStep - BD.CUT_EXTRA) -- Posizione braccio portatesta local bAreCuttingStepsTowardsHead = ( nStartSide == 0) local nSCC = ProcessLongCut.GetSCC( Proc, 0, sMilling, nFaceUse, bInvert, i, nC, bAreCuttingStepsTowardsHead, nil, nil) -- imposto posizione braccio porta testa per non ingombrare agli estremi EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- imposto uso della faccia EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- verifico massimo affondamento rispetto ad elevazione if dElev > dMaxDepth + 10 * GEO.EPS_SMALL then sWarn = 'Warning in LongCut : depth (' .. EgtNumToString( dElev, 1) .. ') bigger than max tool depth (' .. EgtNumToString( dMaxDepth, 1) .. ')' end local dDepth = min( 0, dMaxDepth - dElev ) EgtSetMachiningParam( MCH_MP.DEPTH, dDepth) -- eventuale nota utente per disabilitare controllo ingresso e uscita in grezzo if k < nO then local sNotes = 'OutRaw=3;' EgtSetMachiningParam( MCH_MP.USERNOTES, sNotes) end -- eseguo if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) return false, sErr end end -- eventuale lavorazione della faccia limitante l'inizio if i == 1 and not bStartFixed then -- per il lato sotto il vettore è opposto local vtIni = EgtIf( bFront, X_AX(), -X_AX()) if nSide == -1 then vtIni = -1 * vtIni end for j = 1, Proc.Fct - 1 do local _, vtN = EgtSurfTmFacetCenter( Proc.Id, j, GDB_ID.ROOT) if vtIni * vtN > 0 and nCountMilHead < 2 then MakeSideFace( Proc.Id, j, nSide, sMilling, dToolDiam, nil, nil, bDownHead) nCountMilHead = nCountMilHead + 1 end end if bForcedLim and nCountMilHead < 1 then MakeSideFace( Proc.Id, 0, nSide, sMilling, dToolDiam, bForcedLim, nil, bDownHead) nCountMilHead = nCountMilHead + 1 end end end -- eventuale lavorazione della faccia limitante la fine if not bEndFixed then -- per il lato sotto il vettore è opposto local vtFin = EgtIf( bFront, -X_AX(), X_AX()) if nSide == -1 then vtFin = -1 * vtFin end for j = 1, Proc.Fct - 1 do local _, vtN = EgtSurfTmFacetCenter( Proc.Id, j, GDB_ID.ROOT) if vtFin * vtN > 0 and nCountMilHead < 2 then MakeSideFace( Proc.Id, j, nSide, sMilling, dToolDiam, nil, nil, bDownHead) nCountMilHead = nCountMilHead + 1 end end if bForcedLim and nCountMilHead < 2 then MakeSideFace( Proc.Id, 0, nSide, sMilling, dToolDiam, bForcedLim, nil, bDownHead) nCountMilHead = nCountMilHead + 1 end end -- altrimenti è con fresa di fianco (Long2CutSide) o da sotto (Long2CutDown) else -- 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 -- recupero i dati dell'utensile local dToolDiam = 0 local dToolLength = 0 local dMaxDepth = 0 local dThDiam = 0 local dThLen = 0 if sMilling and 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 sMillingDn 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 -- distanza dalle eventuali facce estreme local dDistToEnd = dToolDiam / 2 local dDistToEndDn = dToolDiamDn / 2 -- calcolo l'elevazione della faccia principale local dFacElev = BL.GetFaceElevation( Proc.Id, 0, nPartId) -- se fresa di fianco o da sotto calcolo quanto l'utensile può andare vicino all'estremo con l'elevazione della faccia minore del raggio utensile if ( nUseMillOnSide <= 1 or nSide == -1) and dFacElev < dToolDiam / 2 then dDistToEnd = sqrt( dFacElev * ( dToolDiam - dFacElev)) end if nUseMillOnSide <= 1 and dFacElev < dToolDiamDn / 2 then dDistToEndDn = sqrt( dFacElev * ( dToolDiamDn - dFacElev)) end -- se la fine è già limitata allora setto per arretrare del raggio utensile if bLimXmin 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 bLimXmin = true end -- larghezza faccia local _, _, dWidth = BL.GetFaceHvRefDim( Proc.Id, 0) -- aggiuntivo sull'affondamento local dAgg = BD.CUT_EXTRA -- determino gli estremi local dStartDist = 0 local dStartAccDist = BD.LONGCUT_ENDLEN local bStartFixed = true if ( bLimXmin and bFront) or ( bLimXmax and not bFront) then if ( bLimXmin and bFront) then dStartDist = EgtIf( nExtendMach == 2, dDistToEnd - dDistToNextPiece + 0.5, dDistToEnd) else dStartDist = dDistToEnd end dStartAccDist = BD.LONGCUT_MAXLEN bStartFixed = false end local dEndDist = 0 local dEndAccDist = BD.LONGCUT_ENDLEN local bEndFixed = true if ( bLimXmin and not bFront) or ( bLimXmax and bFront) then if ( bLimXmin and not bFront) then dEndDist = EgtIf( nExtendMach == 2, dDistToEnd - dDistToNextPiece + 0.5, dDistToEnd) else dEndDist = dDistToEnd end 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 if bStartFixed and bEndFixed then dC = ( dLen - dStartAccDist - dEndAccDist) / nC elseif bStartFixed then dC = ( dLen - dStartAccDist) / ( nC + 1) dEndAccDist = dC elseif bEndFixed then dC = ( dLen - dEndAccDist) / ( nC + 1) dStartAccDist = dC else dC = dLen / ( nC + 2) dStartAccDist = dC dEndAccDist = dC end nC = nC + 2 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 -- verifico se posso farlo da una sola parte o se necessario da due parti local dMaxDepthZ = dMaxDepth local dMaxDepthDnZ = dMaxDepthDn local CosA = abs( vtN:getZ()) if CosA >= 0.05 then local SinA = sqrt( 1 - CosA * CosA) local dRad = dThDiam / 2 - dToolDiam / 2 + BD.COLL_SIC dMaxDepthZ = dMaxDepthZ - ( dRad * CosA / SinA) if sMillingDn then local dRadDn = dThDiamDn / 2 - dToolDiamDn / 2 dMaxDepthDnZ = dMaxDepthDnZ - ( dRadDn * CosA / SinA) end end local dMaxDepthY = dMaxDepth local dMaxDepthDnY = dMaxDepthDn local SinA = abs( vtN:getZ()) if SinA >= 0.05 then local CosA = sqrt( 1 - SinA * SinA) local dRad = dThDiam / 2 - dToolDiam / 2 + BD.COLL_SIC dMaxDepthY = dMaxDepthY - ( dRad * CosA / SinA) if sMillingDn then local dRadDn = dThDiamDn / 2 - dToolDiamDn / 2 dMaxDepthDnY = dMaxDepthDnY - ( dRadDn * CosA / SinA) end end local nPass = 0 local vdMaxD = { 0, 0} local vnHead = { 0, 0} -- con testa da sopra if nSide == 1 or ( sMilling and abs( nSide) == 2 and ( bTopStart or abs( vtN:getY()) < 0.866)) or not sMillingDn then vnHead = { 1, 1} -- se faccia sopra if nSide == 1 then vdMaxD[1] = EgtIf( bLarghAsFace, dMaxDepthY, dMaxDepthZ) if dWidth + dAgg <= vdMaxD[1] then nPass = 1 else nPass = 2 dAgg = BD.CUT_EXTRA_MIN vdMaxD[2] = dMaxDepthY end -- se altrimenti faccia sotto elseif nSide == -1 then if dWidth + dAgg <= dMaxDepthY or abs( vtN:getY()) > EgtIf( BD.C_SIMM, 0.588, 0.7072) then nPass = 1 vdMaxD[1] = dMaxDepthY else nPass = 2 vdMaxD[1] = dMaxDepthY local dDelta = b3Solid:getDimY() - Proc.Box:getDimY() if bLarghAsFace then vdMaxD[2] = min( dMaxDepthY, dMaxDepth - dDelta * abs( vtN:getZ()) - BD.COLL_SIC) else vdMaxD[2] = min( dMaxDepthZ, dToolLength - 5 - dDelta / abs( vtN:getZ()) - BD.COLL_SIC) end if vdMaxD[2] < 0 then nPass = 1 end if nPass == 2 then dAgg = BD.CUT_EXTRA_MIN end end -- altrimenti faccia di fianco else nPass = 1 local dDelta = b3Solid:getMax():getZ() - Proc.Box:getMax():getZ() if abs( vtN:getY()) < 0.866 then vdMaxD[1] = dMaxDepthY elseif bTopStart then vdMaxD[1] = min( dMaxDepthZ, dMaxDepth - dDelta * abs( vtN:getY()) - BD.COLL_SIC) else vdMaxD[1] = min( dMaxDepthY, dToolLength - 5 - dDelta * abs( vtN:getY()) - BD.COLL_SIC) end if vdMaxD[1] < 0 then nPass = 0 end end -- eventuale errore per lavorazione saltata if nPass == 0 then local sErr = 'Error in '..sMchType..' : impossible machining' EgtOutLog( sErr) return false, sErr end -- eventuale avviso per lavorazione incompleta if dWidth + nPass * dAgg > vdMaxD[1] + vdMaxD[2] then sWarn = 'Warning in '..sMchType..' : depth is bigger than max tool depth' end -- con testa da sotto else vnHead = { 2, 2} -- se faccia sotto if nSide == -1 then vdMaxD[1] = EgtIf( bLarghAsFace, dMaxDepthDnY, dMaxDepthDnZ) if dWidth + dAgg <= vdMaxD[1] then nPass = 1 else nPass = 2 dAgg = BD.CUT_EXTRA_MIN vdMaxD[2] = dMaxDepthDnY end -- altrimenti faccia di fianco else nPass = 1 local dDelta = Proc.Box:getMin():getZ() - b3Solid:getMin():getZ() if bBottomStart then vdMaxD[1] = min( dMaxDepthDnZ, dMaxDepthDn - dDelta * abs( vtN:getY()) - BD.COLL_SIC) else vdMaxD[1] = min( dMaxDepthDnY, dToolLengthDn - 5 - dDelta * abs( vtN:getY()) - BD.COLL_SIC) end if vdMaxD[1] < 0 then nPass = 0 end end -- eventuale errore per lavorazione saltata if nPass == 0 then local sErr = 'Error in '..sMchType..' : impossible machining' EgtOutLog( sErr) return false, sErr end -- eventuale avviso per lavorazione incompleta if dWidth + nPass * dAgg > vdMaxD[1] + vdMaxD[2] then sWarn = 'Warning in '..sMchType..' : depth is bigger than max tool depth' end end -- profondità passate local vdDepth = {} vdDepth[1] = min( dWidth + dAgg, vdMaxD[1]) vdDepth[2] = min( dWidth + dAgg - vdDepth[1], vdMaxD[2]) -- ciclo sulle parti local nM = 0 local bMakeMillHeadEnd local bMakeMillHeadStart local dLioPerp1 = dFacElev + BD.COLL_SIC local dLioPerp2 = dWidth * EgtIf( abs( vtN:getZ()) < GEO.EPS_SMALL, 1, sqrt( 1 - vtN:getZ() * vtN:getZ()) / abs( vtN:getZ())) + BD.COLL_SIC -- valore sovrapposizione tra passate local dOverLapExtend = 2 * BD.CUT_EXTRA_MIN for j = 1, nC do -- Limitazioni della lavorazione local nPos = EgtIf( bFront, j, nC - j + 1) local dSal = EgtIf( nPos == 1, -dEndDist, -dEndAccDist - ( nPos - 2) * dC + dOverLapExtend) local dEal = EgtIf( nPos == nC, -dStartDist, -dStartAccDist - ( nC - nPos - 1) * dC + dOverLapExtend) -- Posizione braccio portatesta --local nSCC for k = 1, nPass do -- inserisco le parti di lavorazione nM = nM + 1 local sNameF = EgtIf( vnHead[k] ~= 2, sPrefix, sPrefixDn) .. ( EgtGetName( Proc.Id) or tostring( Proc.Id)) .. '_' .. tostring( nM) local nMchFId = EgtAddMachining( sNameF, EgtIf( vnHead[k] ~= 2, sMilling, sMillingDn)) if not nMchFId then local sErr = 'Error adding machining ' .. sNameF .. '-' .. sMillingDn EgtOutLog( sErr) return false, sErr end -- aggiungo geometria EgtSetMachiningGeometry( {{ Proc.Id, 0}}) -- imposto uso faccia local nFaceUse = EgtIf( vnHead[k] ~= 2, MCH_MILL_FU.PARAL_DOWN, MCH_MILL_FU.PARAL_TOP) if AreSameOrOppositeVectorApprox( vtN, Z_AX()) then nFaceUse = MCH_MILL_FU.PARAL_BACK end EgtSetMachiningParam( MCH_MP.FACEUSE, nFaceUse) -- imposto lato di lavoro e inversione local bInvert if k == 1 then EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) bInvert = true else EgtSetMachiningParam( MCH_MP.WORKSIDE, MCH_MILL_WS.LEFT) EgtSetMachiningParam( MCH_MP.TOOLINVERT, true) bInvert = false dSal, dEal = dEal, dSal end EgtSetMachiningParam( MCH_MP.INVERT, bInvert) -- limito opportunamente la lavorazione EgtSetMachiningParam( MCH_MP.STARTADDLEN, dSal) EgtSetMachiningParam( MCH_MP.ENDADDLEN, dEal) -- assegno affondamento EgtSetMachiningParam( MCH_MP.DEPTH, vdDepth[k]) -- assegno attacco perpendicolare EgtSetMachiningParam( MCH_MP.LIPERP, dLioPerp1) EgtSetMachiningParam( MCH_MP.LOPERP, dLioPerp1) -- step sempre negativi local bAreCuttingStepsTowardsHead = false -- calcolo SCC local nSCC = ProcessLongCut.GetSCC( Proc, 0, EgtIf( vnHead[k] ~= 2, sMilling, sMillingDn), nFaceUse, bInvert, j, nC, bAreCuttingStepsTowardsHead, nil, nil) -- imposto posizione braccio porta testa EgtSetMachiningParam( MCH_MP.SCC, nSCC) -- eseguo if not ML.ApplyMachining( true, false) then -- se feature orientata su faccia da sotto provo a cambiare l'attacco if nSide == -1 then EgtSetMachiningParam( MCH_MP.LIPERP, min( dLioPerp1, dLioPerp2)) EgtSetMachiningParam( MCH_MP.LOPERP, min( dLioPerp1, dLioPerp2)) if not ML.ApplyMachining( true, false) then local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) -- esco se non sono nella seconda lavorazione o non nella faccia da sotto if k < 2 or ( nSide ~= - 1 and not BD.DOWN_HEAD) then return false, sErr end end else local _, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nMchFId, false) -- esco se non sono nella seconda lavorazione o non nella faccia da sotto if k < 2 or ( nSide ~= - 1 and not BD.DOWN_HEAD) then return false, sErr end end end -- eventuale lavorazione della faccia limitante la fine if j == EgtIf( bFront , 1, nC) and not bEndFixed and bRemoveToolRadius then local vtFin = EgtIf( bFront, -X_AX(), X_AX()) for i = 1, Proc.Fct - 1 do local _, vtN = EgtSurfTmFacetCenter( Proc.Id, i, GDB_ID.ROOT) if vtFin * vtN > 0 and not bMakeMillHeadEnd then MakeSideFace( Proc.Id, i, nSide, sMilling, dToolDiam) bMakeMillHeadEnd = true end end if bRemoveToolRadius and not bMakeMillHeadEnd then MakeSideFace( Proc.Id, 0, nSide, sMilling, dToolDiam, bRemoveToolRadius) end end -- eventuale lavorazione della faccia limitante l'inizio if j == EgtIf( bFront , nC, 1) and not bStartFixed and bRemoveToolRadius then local vtIni = EgtIf( bFront, X_AX(), -X_AX()) for i = 1, Proc.Fct - 1 do local _, vtN = EgtSurfTmFacetCenter( Proc.Id, i, GDB_ID.ROOT) if vtIni * vtN > 0 and not bMakeMillHeadStart then MakeSideFace( Proc.Id, i, nSide, sMilling, dToolDiam) bMakeMillHeadStart = true end end if bRemoveToolRadius and not bMakeMillHeadStart then MakeSideFace( Proc.Id, 0, nSide, sMilling, dToolDiam, bRemoveToolRadius) end end end end end return true, sWarn end --------------------------------------------------------------------- return ProcessLongCut