-- MachiningLib.lua by Egalware s.r.l. 2024/04/02 -- Libreria ricerca lavorazioni per Travi -- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE -- Tabella per definizione modulo local MachiningLib = {} -- Include require( 'EgtBase') -- Carico i dati globali local BeamData = require( 'BeamData') local BeamLib = require( 'BeamLib') local FeatureLib = require( 'FeatureLib') EgtOutLog( ' MachiningLib started', 1) --------------------------------------------------------------------- -- TODO da considerare solo angolo 2D?? local function GetToolEntryAngle( Proc, vtTool) local Angle = {} local dSinAngle = -10 * GEO.EPS_SMALL local vtNorm if Proc.AffectedFaces.bTop then vtNorm = Z_AX() dSinAngle = max( dSinAngle, vtTool * vtNorm) end if Proc.AffectedFaces.bBottom then vtNorm = -Z_AX() dSinAngle = max( dSinAngle, vtTool * vtNorm) end if Proc.AffectedFaces.bFront then vtNorm = -Y_AX() dSinAngle = max( dSinAngle, vtTool * vtNorm) end if Proc.AffectedFaces.bBack then vtNorm = Y_AX() dSinAngle = max( dSinAngle, vtTool * vtNorm) end if Proc.AffectedFaces.bLeft then vtNorm = -X_AX() dSinAngle = max( dSinAngle, vtTool * vtNorm) end if Proc.AffectedFaces.bRight then vtNorm = X_AX() dSinAngle = max( dSinAngle, vtTool * vtNorm) end local dCosAngle = sqrt( 1 - sqr( dSinAngle)) local dAngle = acos( dCosAngle) local dTanAngle if dAngle ~= 0 and dAngle ~= 90 then dTanAngle = sqrt( 1 - dCosAngle * dCosAngle) / dCosAngle end Angle.dValue = dAngle Angle.dSin = dSinAngle Angle.dCos = dCosAngle Angle.dTan = dTanAngle return Angle end ------------------------------------------------------------------------------------------------------------- function MachiningLib.StartsLeftSide( Machining) local bStartsLeftSide = ( Machining.vtEdgeDirection:getX() > 10 * GEO.EPS_SMALL and not Machining.bInvert) or ( not( Machining.vtEdgeDirection:getX() > 10 * GEO.EPS_SMALL) and Machining.bInvert) return bStartsLeftSide end ------------------------------------------------------------------------------------------------------------- -- TODO valutare se c'è un modo più preciso di prevedere i casi in cui le lavorazioni dopo separazione sono da saltare function MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) local bCanMoveAfterSplitcut = ( Part.dLength > BeamData.dMinRaw + 10 * GEO.EPS_SMALL) and ( dLengthOnX < 0.7 * Part.dLength - 10 * GEO.EPS_SMALL) return bCanMoveAfterSplitcut end ------------------------------------------------------------------------------------------------------------- function MachiningLib.CanExtendAfterTail( sCanDamageNextPiece, Part) local bCanExtendAfterTail = false if sCanDamageNextPiece == 'ALWAYS' then bCanExtendAfterTail = true elseif sCanDamageNextPiece == 'ONLY_IF_RAWPART' then bCanExtendAfterTail = Part.bIsLastPart end return bCanExtendAfterTail end ------------------------------------------------------------------------------------------------------------- function MachiningLib.GetMachiningSteps( dMachiningDepth, dStep) local MachiningSteps = {} MachiningSteps.dStep = 0 MachiningSteps.nCount = ceil( ( dMachiningDepth - 10 * GEO.EPS_SMALL) / dStep) if MachiningSteps.nCount > 1 then MachiningSteps.dStep = ( dMachiningDepth - dStep) / ( MachiningSteps.nCount - 1) end return MachiningSteps end ------------------------------------------------------------------------------------------------------------- function MachiningLib.GetSplitMachinings( Machinings, vSplittingPoints, Part ) for i = #Machinings, 1, -1 do local nParts = #vSplittingPoints + 1 local dEdgeMaxX = Machinings[i].ptEdge1:getX() local dEdgeMinX = Machinings[i].ptEdge2:getX() if Machinings[i].ptEdge1:getX() < Machinings[i].ptEdge2:getX() - 10 * GEO.EPS_SMALL then dEdgeMaxX = Machinings[i].ptEdge2:getX() dEdgeMinX = Machinings[i].ptEdge1:getX() end local dOriginalStartAddLength = Machinings[i].LeadIn.dStartAddLength local dOriginalEndAddLength = Machinings[i].LeadOut.dEndAddLength if FeatureLib.MachiningNeedsSplitting( Machinings[i].dLengthOnX, Part) then local nCurrentMachiningIndex = i -- lo spezzone attivo è quello precedente al punto di spezzatura corrente for j = 1, nParts do -- check ultimo segmento della lavorazione (NON della feature) local bIsLastSegment = ( nParts == 1) or ( ( ( j ~= 1) and vSplittingPoints[j - 1]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL) and ( j == nParts or vSplittingPoints[j]:getX() < dEdgeMinX + 10 * GEO.EPS_SMALL)) -- se non è l'ultimo segmento della lavorazione, il punto di spezzatura deve essere all'interno del lato che si sta lavorando if ( j ~= nParts and ( vSplittingPoints[j]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL and vSplittingPoints[j]:getX() < dEdgeMaxX - 10 * GEO.EPS_SMALL)) or bIsLastSegment then if j > 1 then nCurrentMachiningIndex = nCurrentMachiningIndex + 1 table.insert( Machinings, nCurrentMachiningIndex, BeamLib.TableCopyDeep( Machinings[i])) end local dStartAddLength = dOriginalStartAddLength local dEndAddLength = dOriginalEndAddLength if MachiningLib.StartsLeftSide( Machinings[i]) then dStartAddLength, dEndAddLength = dEndAddLength, dStartAddLength end if j == 1 then dEndAddLength = - ( vSplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP elseif j == nParts then dStartAddLength = - ( dEdgeMaxX - vSplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP else dStartAddLength = - ( dEdgeMaxX - vSplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP dEndAddLength = - ( vSplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP end if MachiningLib.StartsLeftSide( Machinings[nCurrentMachiningIndex]) then dStartAddLength, dEndAddLength = dEndAddLength, dStartAddLength end Machinings[nCurrentMachiningIndex].LeadIn.dStartAddLength = dStartAddLength Machinings[nCurrentMachiningIndex].LeadOut.dEndAddLength = dEndAddLength end if not bIsLastSegment then Machinings[nCurrentMachiningIndex].bMoveAfterSplitcut = false end Machinings[nCurrentMachiningIndex].nSegment = j end -- anche le lavorazioni non splittate necessitano del segmento assegnato else local dRightAddLength = dOriginalStartAddLength local dLeftAddLength = dOriginalEndAddLength if MachiningLib.StartsLeftSide( Machinings[i]) then dRightAddLength, dLeftAddLength = dLeftAddLength, dRightAddLength end for j = 1, nParts do local dNextSplitX = dEdgeMinX local dPreviousSplitX = dEdgeMaxX if j ~= 1 then dPreviousSplitX = vSplittingPoints[j - 1]:getX() elseif j ~= nParts then dNextSplitX = vSplittingPoints[j]:getX() end if ( dEdgeMinX - dLeftAddLength) > dNextSplitX - 10 * GEO.EPS_SMALL and ( dEdgeMaxX + dRightAddLength) < dPreviousSplitX + 10 * GEO.EPS_SMALL then Machinings[i].nSegment = j end end end end return Machinings end ------------------------------------------------------------------------------------------------------------- -- funzione per cercare utensile tipo FRESA con certe caratteristiche function MachiningLib.FindMill( Proc, ToolSearchParameters) local ToolInfo = {} local nBestToolIndex local dBestToolResidualDepth = 0 for i = 1, #TOOLS do -- prima verifico che utensile sia compatibile local bIsToolCompatible = true -- se viene passato il nome, tutti gli altri sono incompatibili if ToolSearchParameters.sName and ToolSearchParameters.sName ~= TOOLS[i].sName then bIsToolCompatible = false -- si cercano solo frese standard. Se utensile disegnato manualmente, si setta subito che è incompatibile elseif TOOLS[i].bIsProfiledTool then bIsToolCompatible = false -- controlli standard elseif TOOLS[i].dDiameter > ToolSearchParameters.dMaxToolDiameter then bIsToolCompatible = false elseif TOOLS[i].SetupInfo.bIsTopHead and ToolSearchParameters.vtToolDirection:getZ() < TOOLS[i].SetupInfo.dMaxNegativeAngle then bIsToolCompatible = false elseif TOOLS[i].SetupInfo.bIsBottomHead and ToolSearchParameters.vtToolDirection:getZ() > TOOLS[i].SetupInfo.dMaxPositiveAngle then bIsToolCompatible = false elseif ToolSearchParameters.sMillShape == 'STANDARD' and ( TOOLS[i].dSideAngle ~= 0 or TOOLS[i].bIsPen) then bIsToolCompatible = false elseif ToolSearchParameters.sMillShape == 'DOVETAIL' and not TOOLS[i].bIsDoveTail then bIsToolCompatible = false elseif ToolSearchParameters.sMillShape == 'TSHAPEMILL' and not TOOLS[i].bIsTMill then bIsToolCompatible = false elseif ToolSearchParameters.sMillShape == 'PEN' and not TOOLS[i].bIsPen then bIsToolCompatible = false elseif TOOLS[i].sType ~= ToolSearchParameters.sType then -- se sto cercando una fresa che non può lavorare di testa, quelle che lavorano di testa sono comunque ammesse if TOOLS[i].sType == 'MILL_STD' and ToolSearchParameters.sType == 'MILL_NOTIP' then bIsToolCompatible = true else bIsToolCompatible = false end end -- scelgo il migliore if bIsToolCompatible then -- calcolo riduzione del massimo materiale utilizzabile local ToolEntryAngle = GetToolEntryAngle( Proc, ToolSearchParameters.vtToolDirection) -- se ToolHolder più grande dell'utensile, il primo oggetto in collisione è il ToolHolder. Altrimenti il motore. local dDimObjToCheck = EgtIf( TOOLS[i].ToolHolder.dDiameter > TOOLS[i].dDiameter, TOOLS[i].ToolHolder.dDiameter, BeamData.C_SIMM_ENC) local dCurrentMaxMatReduction = BeamData.COLL_SIC or 5 -- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom) -- TODO considerare anche il caso in cui lo stelo sia più grande del diametro utensile -- TODO nei confronti tra valori gestire tolleranze -- calcolo riduzione per non toccare con ToolHolder / Motore if ToolEntryAngle.dValue > 0 and ToolEntryAngle.dValue < 90 then dCurrentMaxMatReduction = dCurrentMaxMatReduction / ToolEntryAngle.dSin + ( ( dDimObjToCheck - TOOLS[i].dDiameter) / 2) / ToolEntryAngle.dTan end -- dCurrMachReduction = negativo -> limitare, positivo -> mm extra disponibili local dCurrentResidualDepth = ToolSearchParameters.dElevation + dCurrentMaxMatReduction - TOOLS[i].dMaxDepth -- se non ancora trovato, oppure se completo e il migliore fino ad ora non è completo: corrente è il migliore if not nBestToolIndex or ( dBestToolResidualDepth > 0 and dCurrentResidualDepth <= 0) then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth -- altrimenti scelgo il migliore else -- se entrambi completi if dBestToolResidualDepth <= 0 and dCurrentResidualDepth <= 0 then -- se il migliore era su aggregato e corrente montanto direttamente, prediligo utensile montato direttamente if not TOOLS[i].SetupInfo.bToolOnAggregate and TOOLS[i].SetupInfo.bToolOnAggregate then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth -- se hanno stesso montaggio elseif TOOLS[i].SetupInfo.bToolOnAggregate == TOOLS[nBestToolIndex].SetupInfo.bToolOnAggregate then -- scelgo utensile con indice di bontà utensile calcolato come: lunghezza / massimo materiale / diametro if ( TOOLS[i].dLength / TOOLS[i].dMaxMaterial) / TOOLS[i].dDiameter < ( TOOLS[nBestToolIndex].dLength / TOOLS[nBestToolIndex].dMaxMaterial) / TOOLS[nBestToolIndex].dDiameter then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth end end -- se entrambi incompleti elseif dBestToolResidualDepth > 0 and dCurrentResidualDepth > 0 then --scelgo quello che lavora di più if dCurrentResidualDepth < dBestToolResidualDepth then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth end end end end end ToolInfo.nToolIndex = nBestToolIndex ToolInfo.dResidualDepth = dBestToolResidualDepth return ToolInfo end ------------------------------------------------------------------------------------------------------------- -- funzione per cercare utensile tipo LAMA con certe caratteristiche -- TODO da completare function MachiningLib.FindBlade( Proc, ToolSearchParameters) local ToolInfo = {} -- parametri obbligatori if type( ToolSearchParameters.vtToolDirection) ~= 'table' then error( 'FindBlade : missing tool direction') end if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then error( 'FindBlade : missing top head info') end if type( ToolSearchParameters.bAllowBottomHead) ~= 'boolean' then error( 'FindBlade : missing bottom head info') end if not ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then error( 'FindBlade : wrong head info') end -- parametri opzionali ToolSearchParameters.dElevation = ToolSearchParameters.dElevation or 0 ToolSearchParameters.bForceLongcutBlade = ToolSearchParameters.bForceLongcutBlade or false local nBestToolIndex for i = 1, #TOOLS do local bIsToolCompatible = false if TOOLS[i].sFamily == 'SAWBLADE' then if ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then bIsToolCompatible = TOOLS[i].SetupInfo.bIsTopHead elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then bIsToolCompatible = TOOLS[i].SetupInfo.bIsBottomHead end end if bIsToolCompatible then if not nBestToolIndex then nBestToolIndex = i else -- prediligo utensile per tagli lunghi, se richiesto if ToolSearchParameters.bForceLongcutBlade and not TOOLS[nBestToolIndex].bIsUsedForLongCut and TOOLS[i].bIsUsedForLongCut then nBestToolIndex = i end end end end ToolInfo.nToolIndex = nBestToolIndex return ToolInfo end ------------------------------------------------------------------------------------------------------------- -- funzione per cercare utensile tipo PUNTA A FORARE con certe caratteristiche -- TODO da fare function MachiningLib.FindDrill() end ------------------------------------------------------------------------------------------------------------- -- funzione per cercare utensile tipo SEGA A CATENA con certe caratteristiche -- TODO da completare function MachiningLib.FindChainSaw( Proc, ToolSearchParameters) local ToolInfo = {} -- parametri obbligatori if type( ToolSearchParameters.vtToolDirection) ~= 'table' then error( 'FindBlade : missing tool direction') end if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then error( 'FindBlade : missing top head info') end if type( ToolSearchParameters.bAllowBottomHead) ~= 'boolean' then error( 'FindBlade : missing bottom head info') end if not ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then error( 'FindBlade : wrong head info') end -- parametri opzionali ToolSearchParameters.dElevation = ToolSearchParameters.dElevation or 0 ToolSearchParameters.bExtendWithCornerRadius = ToolSearchParameters.bExtendWithCornerRadius or false local nBestToolIndex local dBestToolResidualDepth = 0 for i = 1, #TOOLS do local bIsToolCompatible = false if TOOLS[i].sFamily == 'MORTISE' then if ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then bIsToolCompatible = TOOLS[i].SetupInfo.bIsTopHead elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then bIsToolCompatible = TOOLS[i].SetupInfo.bIsBottomHead else bIsToolCompatible = true end end -- TODO nei confronti tra valori gestire tolleranze if bIsToolCompatible then if ToolSearchParameters.dElevation > 10 * GEO.EPS_SMALL and ToolSearchParameters.bExtendWithCornerRadius then ToolSearchParameters.dElevation = ToolSearchParameters.dElevation + TOOLS[i].dCornerRadius end -- TODO gestire accorciamento massimo materiale per inclinazione local dCurrentResidualDepth = ToolSearchParameters.dElevation - TOOLS[i].dMaxDepth -- se non ancora trovato, oppure se completo e il migliore fino ad ora non è completo: corrente è il migliore if not nBestToolIndex or ( dBestToolResidualDepth > 0 and dCurrentResidualDepth <= 0) then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth -- altrimenti scelgo il migliore else -- se entrambi completi if dBestToolResidualDepth <= 0 and dCurrentResidualDepth <= 0 then -- scelgo utensile con rapporto lunghezza / diametro minore if ( TOOLS[i].dLength / pow( TOOLS[i].dDiameter, 1.5)) < ( TOOLS[nBestToolIndex].dLength / pow( TOOLS[nBestToolIndex].dDiameter, 1.5)) then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth end -- se entrambi incompleti elseif dBestToolResidualDepth > 0 and dCurrentResidualDepth > 0 then --scelgo quello che lavora di più if dCurrentResidualDepth > dBestToolResidualDepth then nBestToolIndex = i dBestToolResidualDepth = dCurrentResidualDepth end end end end end ToolInfo.nToolIndex = nBestToolIndex ToolInfo.dResidualDepth = dBestToolResidualDepth return ToolInfo end ------------------------------------------------------------------------------------------------------------- -- salva in lista globale la lavorazione appena calcolata function MachiningLib.AddNewMachining( ProcToAdd, MachiningToAdd, AuxiliaryDataToAdd) -- Controllo parametri obbligatori if not MachiningToAdd.nType or not MachiningToAdd.nToolIndex or not MachiningToAdd.Geometry or not ProcToAdd.id then return false end -- se nome non definito, assegno alla lavorazioen un nome standard if not MachiningToAdd.sOperationName then -- Drilling if MachiningToAdd.nType == MCH_MY.DRILLING then MachiningToAdd.sTypeName = 'Drill_' -- Milling elseif MachiningToAdd.nType == MCH_MY.MILLING then -- se utensile lama if TOOLS[MachiningToAdd.nToolIndex].sFamily == 'SAWBLADE' then MachiningToAdd.sTypeName = 'Cut_' else MachiningToAdd.sTypeName = 'Mill_' end -- Pocketing elseif MachiningToAdd.nType == MCH_MY.POCKETING then MachiningToAdd.sTypeName = 'Pocket_' -- Mortising elseif MachiningToAdd.nType == MCH_MY.MORTISING then MachiningToAdd.sTypeName = 'ChSaw_' end MachiningToAdd.sOperationName = MachiningToAdd.sTypeName .. ( EgtGetName( ProcToAdd.id) or tostring( ProcToAdd.id)) -- .. '_' .. tostring( MachiningToAdd.Geometry) end if not MachiningToAdd.sToolName then MachiningToAdd.sToolName = TOOLS[MachiningToAdd.nToolIndex].sName end local Machining = {} Machining.Proc = ProcToAdd Machining.Machining = MachiningToAdd Machining.AuxiliaryData = AuxiliaryDataToAdd or {} table.insert( MACHININGS, Machining) return true end ------------------------------------------------------------------------------------------------------------- -- funzione per aggiungere una nuova lavorazione function MachiningLib.AddOperations( vProc, Part, sRotation) local nErr local sErr = '' local bAreAllMachiningApplyOk = true local bSplitExecuted = false -- parametri generali lavorazione local MachiningParameters = { { sName = 'sDepth', nMchParam = MCH_MP.DEPTH_STR}, { sName = 'bInvert', nMchParam = MCH_MP.INVERT}, { sName = 'nWorkside', nMchParam = MCH_MP.WORKSIDE}, { sName = 'nFaceuse', nMchParam = MCH_MP.FACEUSE}, { sName = 'nSCC', nMchParam = MCH_MP.SCC}, { sName = 'bToolInvert', nMchParam = MCH_MP.TOOLINVERT}, { sName = 'sBlockedAxis', nMchParam = MCH_MP.BLOCKEDAXIS}, { sName = 'sInitialAngles', nMchParam = MCH_MP.INITANGS}, { sName = 'nHeadSide', nMchParam = MCH_MP.HEADSIDE}, { sName = 'nSubType', nMchParam = MCH_MP.SUBTYPE}, { sName = 'dOverlap', nMchParam = MCH_MP.OVERL}, { sName = 'nStepType', nMchParam = MCH_MP.STEPTYPE}, { sName = 'dStartSafetyLength', nMchParam = MCH_MP.STARTPOS}, { sName = 'dReturnPos', nMchParam = MCH_MP.RETURNPOS}, { sName = 'dRadialOffset', nMchParam = MCH_MP.OFFSR}, { sName = 'dLongitudinalOffset', nMchParam = MCH_MP.OFFSL}, { sName = 'dStartSlowLen', nMchParam = MCH_MP.STARTSLOWLEN}, { sName = 'dEndSlowLen', nMchParam = MCH_MP.ENDSLOWLEN}, { sName = 'dThrouAddLen', nMchParam = MCH_MP.THROUADDLEN}, { sName = 'sSystemNotes', nMchParam = MCH_MP.SYSNOTES}, { sName = 'sUserNotes', nMchParam = MCH_MP.USERNOTES} } -- parametri relativi allo step MachiningParameters.Steps = { { sName = 'nStepType', nMchParam = MCH_MP.STEPTYPE}, { sName = 'dStep', nMchParam = MCH_MP.STEP}, { sName = 'dSideStep', nMchParam = MCH_MP.SIDESTEP} } -- parametri relativi all'approccio MachiningParameters.LeadIn = { { sName = 'nType', nMchParam = MCH_MP.LEADINTYPE}, { sName = 'dStartAddLength', nMchParam = MCH_MP.STARTADDLEN}, { sName = 'dTangentDistance', nMchParam = MCH_MP.LITANG}, { sName = 'dPerpDistance', nMchParam = MCH_MP.LIPERP}, { sName = 'dElevation', nMchParam = MCH_MP.LIELEV}, { sName = 'dCompLength', nMchParam = MCH_MP.LICOMPLEN} } -- parametri relativi alla retrazione MachiningParameters.LeadOut = { { sName = 'nType', nMchParam = MCH_MP.LEADOUTTYPE}, { sName = 'dEndAddLength', nMchParam = MCH_MP.ENDADDLEN}, { sName = 'dTangentDistance', nMchParam = MCH_MP.LOTANG}, { sName = 'dPerpDistance', nMchParam = MCH_MP.LOPERP}, { sName = 'dElevation', nMchParam = MCH_MP.LOELEV}, { sName = 'dCompLength', nMchParam = MCH_MP.LOCOMPLEN} } -- parametri da scrivere nelle note utente local UserNotes = { { sName = 'dMaxElev', sMchParam = 'MaxElev'}, { sName = 'dOpenMinSafe', sMchParam = 'OpenMinSafe'}, { sName = 'nVMRS', sMchParam = 'VMRS'}, { sName = 'dStartZmax', sMchParam = 'StartZmax'}, { sName = 'nOutRaw', sMchParam = 'OutRaw'}, { sName = 'nOpenOutRaw', sMchParam = 'OpenOutRaw'}, { sName = 'nPlunge', sMchParam = 'Plunge'} } -- parametri da scrivere nelle note di sistema local SystemNotes = { } for i = 1, #MACHININGS do -- si aggiungono solo quelle della fase richiesta if ( sRotation == 'STD' and not MACHININGS[i].Proc.bDown and not MACHININGS[i].Proc.bSide) or ( MACHININGS[i].Proc.bDown and sRotation == 'DOWN') or ( MACHININGS[i].Proc.bSide and sRotation == 'SIDE') then local nClonesToAdd = 1 if MACHININGS[i].AuxiliaryData.Clones then nClonesToAdd = #MACHININGS[i].AuxiliaryData.Clones end for j = 1, nClonesToAdd do -- creazione lavorazione local nOperationId = EgtCreateMachining( MACHININGS[i].Machining.sOperationName, MACHININGS[i].Machining.nType, MACHININGS[i].Machining.sToolName) if nOperationId then -- impostazione geometria local Geometry if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].Geometry then Geometry = MACHININGS[i].AuxiliaryData.Clones[j].Geometry elseif MACHININGS[i].Machining.Geometry then Geometry = MACHININGS[i].Machining.Geometry end EgtSetMachiningGeometry( Geometry) -- impostazione parametri lavorazione -- TODO scrivere sempre Steps, LeadIn, LeadOut nelle tabelle in modo da non dover controllare ogni volta che ci siano for k = 1, #MachiningParameters do local sValue if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][MachiningParameters[k].sName] then sValue = MACHININGS[i].AuxiliaryData.Clones[j][MachiningParameters[k].sName] elseif MACHININGS[i].Machining[MachiningParameters[k].sName] then sValue = MACHININGS[i].Machining[MachiningParameters[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters[k].nMchParam, sValue) end end for k = 1, #MachiningParameters.Steps do local sValue if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].Steps and MACHININGS[i].AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName] then sValue = MACHININGS[i].AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName] elseif MACHININGS[i].Machining.Steps and MACHININGS[i].Machining.Steps[MachiningParameters.Steps[k].sName] then sValue = MACHININGS[i].Machining.Steps[MachiningParameters.Steps[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters.Steps[k].nMchParam, sValue) end end for k = 1, #MachiningParameters.LeadIn do local sValue if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].LeadIn and MACHININGS[i].AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName] then sValue = MACHININGS[i].AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName] elseif MACHININGS[i].Machining.LeadIn and MACHININGS[i].Machining.LeadIn[MachiningParameters.LeadIn[k].sName] then sValue = MACHININGS[i].Machining.LeadIn[MachiningParameters.LeadIn[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters.LeadIn[k].nMchParam, sValue) end end for k = 1, #MachiningParameters.LeadOut do local sValue if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].LeadOut and MACHININGS[i].AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName] then sValue = MACHININGS[i].AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName] elseif MACHININGS[i].Machining.LeadOut and MACHININGS[i].Machining.LeadOut[MachiningParameters.LeadOut[k].sName] then sValue = MACHININGS[i].Machining.LeadOut[MachiningParameters.LeadOut[k].sName] end if sValue then EgtSetMachiningParam( MachiningParameters.LeadOut[k].nMchParam, sValue) end end for k = 1, #UserNotes do local sValue if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][UserNotes[k].sName] then sValue = MACHININGS[i].AuxiliaryData.Clones[j][UserNotes[k].sName] elseif MACHININGS[i].Machining[UserNotes[k].sName] then sValue = MACHININGS[i].Machining[UserNotes[k].sName] end if sValue then local sUserNotes = '' sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) sUserNotes = EgtSetValInNotes( sUserNotes, UserNotes[k].sMchParam, sValue) EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) end end -- parametri da settare nelle note di sistema -- TODO da decidere quali sono le note da salvare qui. Probabilmente tutte quelle relative all'ordine delle lavorazioni --if MACHININGS[i].Machining.nMachiningOrder then -- sSystemNotes = EgtSetValInNotes( sSystemNotes, 'MachiningOrder', MACHININGS[i].Machining.nMachiningOrder) --end for k = 1, #SystemNotes do local sValue if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][SystemNotes[k].sName] then sValue = MACHININGS[i].AuxiliaryData.Clones[j][SystemNotes[k].sName] elseif MACHININGS[i].Machining[SystemNotes[k].sName] then sValue = MACHININGS[i].Machining[SystemNotes[k].sName] end if sValue then local sSystemNotes = '' sSystemNotes = EgtGetMachiningParam( MCH_MP.SYSNOTES) sSystemNotes = EgtSetValInNotes( sSystemNotes, SystemNotes[k].sMchParam, sValue) EgtSetMachiningParam( MCH_MP.SYSNOTES, sSystemNotes) end end local bIsApplyOk = MachiningLib.ApplyMachining( true, false) if not bIsApplyOk then bAreAllMachiningApplyOk = false nErr, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nOperationId, false) end -- TODO è giusto inserire queste info alla fine della lavorazione? oppure conviene creare un record in MACHININGS apposito per la disposizione? -- se era taglio di separazione, aggiungo nuova fase if MACHININGS[i].AuxiliaryData.bAddNewPhase then bSplitExecuted = true BeamLib.AddPhaseWithRawParts( MACHININGS[i].Proc.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET) -- se grezzo successivo senza pezzi e finale, va tolto local nNextRawId = EgtGetNextRawPart( MACHININGS[i].Proc.idRaw) if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BeamData.dMinRaw then EgtRemoveRawPartFromCurrPhase( nNextRawId) end local nPhase = EgtGetCurrPhase() local nDispId = EgtGetPhaseDisposition( nPhase) if sRotation == 'DOWN' then local nRotation = EgtIf( Part.nInitialPosition + 2 > 4, Part.nInitialPosition + 2 - 4, Part.nInitialPosition + 2) BeamLib.RotatePart( Part, nRotation) EgtSetInfo( nDispId, 'ROT', -2) EgtSetInfo( nDispId, 'TYPE', 'MID2') elseif sRotation == 'SIDE' then local nRotation = EgtIf( Part.nInitialPosition + 1 > 4, Part.nInitialPosition + 1 - 4, Part.nInitialPosition + 1) BeamLib.RotatePart( Part, nRotation) EgtSetInfo( nDispId, 'ROT', -1) EgtSetInfo( nDispId, 'TYPE', 'MID2') else local nRotation = Part.nInitialPosition BeamLib.RotatePart( Part, nRotation) EgtSetInfo( nDispId, 'TYPE', 'END') end EgtSetInfo( nDispId, 'ORD', MACHININGS[i].Proc.nIndexPartInParts) end else return false, 'UNEXPECTED ERROR: Error on creating machining', bSplitExecuted end end end end return bAreAllMachiningApplyOk, sErr, bSplitExecuted end ------------------------------------------------------------------------------------------------------------- function MachiningLib.ApplyMachining( bRecalc, bApplyPost) local bResult = EgtApplyMachining( bRecalc, bApplyPost) return bResult end ------------------------------------------------------------------------------------------------------------- -- funzione che restituisce l'indice MRR (Material Removal Rate) della strategia. Dati in ingresso: Step, SideStep, Feed, ToolIndex, MachiningType function MachiningLib.GetToolMRR( Parameters) local dMRR = 1 -- se ho già tutti i parametri if not Parameters.dStep or not Parameters.dSideStep or not Parameters.dFeed then -- se manca qualche parametro, lo recupero da parametro di default dell'utensile if Parameters.nToolIndex then Parameters.dStep = Parameters.dStep or TOOLS[Parameters.nToolIndex].dStep Parameters.dSideStep = Parameters.dSideStep or TOOLS[Parameters.nToolIndex].dSideStep Parameters.dFeed = Parameters.dFeed or TOOLS[Parameters.nToolIndex].Feeds.dFeed -- se non riesco a calcolare, ritorno un indice molto basso else return GEO.EPS_SMALL end end dMRR = Parameters.dStep * Parameters.dSideStep * Parameters.dFeed -- Unità: dm/min per avere un indice vicino alle unità return dMRR / pow( 10, 6) end ------------------------------------------------------------------------------------------------------------- return MachiningLib