Files
databeamnew/LuaLibs/MachiningLib.lua
T
luca.mazzoleni 36f1ae5513 - calcolo lunghezza stimata del percorso con attacchi centralizzata, in MachiningLib
- calcolo lunghezza stimata aggiunto anche nel caso di lavorazione splittata
2025-04-08 17:51:01 +02:00

1102 lines
52 KiB
Lua

-- 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)
else
MachiningSteps.dStep = dMachiningDepth
MachiningSteps.nCount = 1
end
return MachiningSteps
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.GetSplitMachinings( Machinings, SplittingPoints, Part )
for i = #Machinings, 1, -1 do
local nParts = #SplittingPoints + 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
local sOriginalStage = Machinings[i].sStage
if FeatureLib.IsMachiningLong( 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 SplittingPoints[j - 1]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL)
and ( j == nParts or SplittingPoints[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 ( SplittingPoints[j]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL and SplittingPoints[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 = - ( SplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( SplittingPoints[j]:getX() + ( dEdgeMaxX - SplittingPoints[j]:getX()) / 2, 0, 0)
elseif j == nParts then
dStartAddLength = - ( dEdgeMaxX - SplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( dEdgeMinX + ( SplittingPoints[j - 1]:getX() - dEdgeMinX) / 2, 0, 0)
else
dStartAddLength = - ( dEdgeMaxX - SplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
dEndAddLength = - ( SplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( SplittingPoints[j]:getX() + ( SplittingPoints[j - 1]:getX() - SplittingPoints[j]:getX()) / 2, 0, 0)
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].sStage = ''
else
Machinings[nCurrentMachiningIndex].sStage = sOriginalStage
end
Machinings[nCurrentMachiningIndex].nFeatureSegment = j
Machinings[nCurrentMachiningIndex].dLengthToMachine = Machinings[nCurrentMachiningIndex].dEdgeLength + Machinings[nCurrentMachiningIndex].LeadIn.dStartAddLength + Machinings[nCurrentMachiningIndex].LeadOut.dEndAddLength
Machinings[nCurrentMachiningIndex].dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetLengthToMachineAllStepsWithLeadInOut( Machinings[nCurrentMachiningIndex])
end
-- anche le lavorazioni non splittate necessitano del segmento assegnato
else
local dRightAddLength = 0
local dLeftAddLength = 0
-- si considerano allungamenti e accorciamenti solo se la feature è orientata principalmente lungo X
-- TODO il modo corretto è proiettare tutto, allungamenti e accorciamenti compresi, sulla faccia frontale
if abs( Machinings[i].vtToolDirection:getX()) < 0.707 then
dRightAddLength = dOriginalStartAddLength
dLeftAddLength = dOriginalEndAddLength
if MachiningLib.StartsLeftSide( Machinings[i]) then
dRightAddLength, dLeftAddLength = dLeftAddLength, dRightAddLength
end
end
for j = 1, nParts do
local dNextSplitX = dEdgeMinX
local dPreviousSplitX = dEdgeMaxX
if j ~= 1 then
dPreviousSplitX = SplittingPoints[j - 1]:getX()
end
if j ~= nParts then
dNextSplitX = SplittingPoints[j]:getX()
end
if ( dEdgeMinX - dLeftAddLength) > dNextSplitX - 10 * GEO.EPS_SMALL and ( dEdgeMinX - dLeftAddLength) < dPreviousSplitX + 10 * GEO.EPS_SMALL then
Machinings[i].nFeatureSegment = j
Machinings[i].ptCenter = Point3d( dNextSplitX + ( dPreviousSplitX - dNextSplitX) / 2, 0, 0)
end
end
Machinings[i].dLengthToMachine = Machinings[i].dEdgeLength + Machinings[i].LeadIn.dStartAddLength + Machinings[i].LeadOut.dEndAddLength
Machinings[i].dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetLengthToMachineAllStepsWithLeadInOut( Machinings[i])
end
end
return Machinings
end
-------------------------------------------------------------------------------------------------------------
-- funzione per cercare utensile tipo FRESA con certe caratteristiche
-- TODO qui vtToolDirection è in realtà vtN
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 ToolSearchParameters.dMaxToolDiameter and TOOLS[i].dDiameter > ToolSearchParameters.dMaxToolDiameter then
bIsToolCompatible = false
elseif TOOLS[i].SetupInfo.HeadType.bTop and ToolSearchParameters.vtToolDirection:getZ() < TOOLS[i].SetupInfo.GetMinNz( ToolSearchParameters.vtToolDirection) - GEO.EPS_ZERO then
bIsToolCompatible = false
elseif TOOLS[i].SetupInfo.HeadType.bBottom and ToolSearchParameters.vtToolDirection:getZ() > TOOLS[i].SetupInfo.GetMaxNz( ToolSearchParameters.vtToolDirection) + GEO.EPS_ZERO 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 ToolSearchParameters.sType and 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, TOOLS[i].SetupInfo.dCAxisEncumbrance)
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
-- dCurrentResidualDepth = negativo -> mm extra disponibili, positivo -> limitare
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[nBestToolIndex].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].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex 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
-- TODO il FindBlade dovrà restituire di utilizzare sempre la lama sopra se l'angolo lo permette, ma avendo un'altezza massima (da macchina) oltre cui il DownUp non sarà fattibile (evita collisioni tra asse e pezzo)
function MachiningLib.FindBlade( Proc, ToolSearchParameters)
local ToolInfo = {}
-- parametri obbligatori
if type( ToolSearchParameters.vtN) ~= '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
local dBestToolResidualDepth = 0
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.HeadType.bTop
elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then
bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bBottom
else
bIsToolCompatible = true
end
end
-- check angolo limite lama
if TOOLS[i].SetupInfo.HeadType.bTop and ToolSearchParameters.vtN:getZ() < TOOLS[i].SetupInfo.GetMinNz( ToolSearchParameters.vtN) - GEO.EPS_ZERO then
bIsToolCompatible = false
end
if TOOLS[i].SetupInfo.HeadType.bBottom and ToolSearchParameters.vtN:getZ() > TOOLS[i].SetupInfo.GetMaxNz( ToolSearchParameters.vtN) + GEO.EPS_ZERO then
bIsToolCompatible = false
end
if bIsToolCompatible then
-- TODO gestire accorciamento massimo materiale per inclinazione
local dCurrentResidualDepth = ToolSearchParameters.dElevation - TOOLS[i].dMaxDepth
if not nBestToolIndex or ( dBestToolResidualDepth > 0 and dCurrentResidualDepth <= 10 * GEO.EPS_SMALL) then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
else
-- prediligo utensile per tagli lunghi, se richiesto
if ToolSearchParameters.bForceLongcutBlade and not TOOLS[nBestToolIndex].bIsUsedForLongCut and TOOLS[i].bIsUsedForLongCut then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
else
-- entrambi completi
if dBestToolResidualDepth <= 10 * GEO.EPS_SMALL and dCurrentResidualDepth <= 10 * GEO.EPS_SMALL then
-- si sceglie quello con le performance migliori
if TOOLS[i].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex + 10 * GEO.EPS_SMALL then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
end
-- entrambi incompleti
elseif dBestToolResidualDepth > 10 * GEO.EPS_SMALL and dCurrentResidualDepth > 10 * GEO.EPS_SMALL then
-- si sceglie quello che lavora di più
if dCurrentResidualDepth > dBestToolResidualDepth then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
end
end
end
end
end
end
ToolInfo.nToolIndex = nBestToolIndex
ToolInfo.dResidualDepth = dBestToolResidualDepth
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( 'FindChainSaw : missing tool direction')
end
if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then
error( 'FindChainSaw : missing top head info')
end
if type( ToolSearchParameters.bAllowBottomHead) ~= 'boolean' then
error( 'FindChainSaw : missing bottom head info')
end
if not ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then
error( 'FindChainSaw : 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.HeadType.bTop
elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then
bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bBottom
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].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
end
-- se entrambi incompleti
elseif dBestToolResidualDepth > 10 * GEO.EPS_SMALL and dCurrentResidualDepth > 10 * GEO.EPS_SMALL 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
local function 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)
-- aggiornamento info generiche lavorazioni
local nHeadCutRotation
if ProcToAdd.bDown then
nHeadCutRotation = 3
elseif ProcToAdd.bSide then
nHeadCutRotation = 2
else
nHeadCutRotation = 1
end
MACHININGS.Info.nHeadCutRotation = max( MACHININGS.Info.nHeadCutRotation or 0, nHeadCutRotation)
local nSplitCutRotation
if ProcToAdd.bDown and MachiningToAdd.sStage == 'AfterTail' then
nSplitCutRotation = 3
elseif ProcToAdd.bSide and MachiningToAdd.sStage == 'AfterTail' then
nSplitCutRotation = 2
else
nSplitCutRotation = 1
end
MACHININGS.Info.nSplitCutRotation = max( MACHININGS.Info.nSplitCutRotation or 0, nSplitCutRotation)
return true
end
-------------------------------------------------------------------------------------------------------------
-- TODO funziona solo con attacco perpendicolare - da aggiungere gestione in caso di attacco tangenziale
function MachiningLib.AddMachinings( Proc, Machining, AuxiliaryData)
local bMachiningAdded = false
if Machining.CloneStepsHorizontal and Machining.CloneStepsHorizontal.nCount > 1 then
if not AuxiliaryData then
AuxiliaryData = {}
end
AuxiliaryData.Clones = {}
local dOriginalRadialOffset = Machining.dRadialOffset
local dOriginalLeadInPerpDistance = Machining.LeadIn.dPerpDistance
local dOriginalLeadOutPerpDistance = Machining.LeadOut.dPerpDistance
for i = 1, Machining.CloneStepsHorizontal.nCount do
AuxiliaryData.Clones[i] = {}
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffset + Machining.CloneStepsHorizontal.dStep * ( Machining.CloneStepsHorizontal.nCount - i)
-- update distanza perpendicolare attacco per contemplare l'offset applicato
if abs( dOriginalLeadInPerpDistance) > 10 * GEO.EPS_SMALL and abs( dOriginalLeadOutPerpDistance) > 10 * GEO.EPS_SMALL then
AuxiliaryData.Clones[i].LeadIn = {}
AuxiliaryData.Clones[i].LeadOut = {}
AuxiliaryData.Clones[i].LeadIn.dPerpDistance = dOriginalLeadInPerpDistance - AuxiliaryData.Clones[i].dRadialOffset + dOriginalRadialOffset
AuxiliaryData.Clones[i].LeadOut.dPerpDistance = dOriginalLeadOutPerpDistance - AuxiliaryData.Clones[i].dRadialOffset + dOriginalRadialOffset
end
end
elseif Machining.CloneStepsVertical and Machining.CloneStepsVertical.nCount > 1 then
if not AuxiliaryData then
AuxiliaryData = {}
end
AuxiliaryData.Clones = {}
local dOriginalRadialOffset = Machining.dRadialOffset
for i = Machining.CloneStepsVertical.nCount, 1, -1 do
AuxiliaryData.Clones[i] = {}
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffset + Machining.CloneStepsVertical.dStep * ( i - 1)
end
end
bMachiningAdded = AddNewMachining( Proc, Machining, AuxiliaryData)
return bMachiningAdded
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'},
{ sName = 'vtFaceUse', sMchParam = 'VtFaceUse'}
}
-- 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)
-- si scrive info pezzo e feature su geometria lavorazione
if Geometry then
EgtSetInfo( Geometry[1][1], 'CUTID', MACHININGS[i].Proc.idCut)
EgtSetInfo( Geometry[1][1], 'TASKID', MACHININGS[i].Proc.idTask)
end
-- 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.bIsSplitOrCut 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
BeamLib.RotatePart( Part, Part.nInitialPosition - 3)
EgtSetInfo( nDispId, 'ROT', -2)
EgtSetInfo( nDispId, 'TYPE', 'MID2')
elseif sRotation == 'SIDE' then
BeamLib.RotatePart( Part, Part.nInitialPosition - 2)
EgtSetInfo( nDispId, 'ROT', -1)
EgtSetInfo( nDispId, 'TYPE', 'MID2')
else
BeamLib.RotatePart( Part, Part.nInitialPosition - 1)
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
-------------------------------------------------------------------------------------------------------------
function MachiningLib.GetLengthToMachineAllStepsWithLeadInOut( Machining)
local dLengthToMachineAllStepsWithLeadInOut = 0
if Machining.nType == MCH_OY.MILLING then
if Machining.Steps.nStepType == MCH_MILL_ST.ZIGZAG then
dLengthToMachineAllStepsWithLeadInOut = ( Machining.dLengthToMachine * Machining.CloneStepsHorizontal.nCount + ( Machining.LeadIn.dTotalEstimatedDistance + Machining.LeadOut.dTotalEstimatedDistance)) * Machining.Steps.nCount
else
dLengthToMachineAllStepsWithLeadInOut = Machining.CloneStepsHorizontal.nCount * ( Machining.dLengthToMachine + Machining.LeadIn.dTotalEstimatedDistance + Machining.LeadOut.dTotalEstimatedDistance) * Machining.Steps.nCount
end
elseif Machining.nType == MCH_OY.MORTISING then
if Machining.Steps.nStepType == MCH_MILL_ST.ZIGZAG then
dLengthToMachineAllStepsWithLeadInOut = ( Machining.dLengthToMachine * Machining.Steps.nCount + 2 * ( Machining.dDepthToMachine + ( TOOLS[Machining.nToolIndex].SetupInfo.dZSafeDelta or 60) + EgtMdbGetGeneralParam( MCH_GP.SAFEZ))) * Machining.CloneStepsVertical.nCount
else
dLengthToMachineAllStepsWithLeadInOut = Machining.CloneStepsVertical.nCount * ( ( 2 * Machining.Steps.nCount - 1) * Machining.dLengthToMachine + 2 * 10 * ( Machining.Steps.nCount - 1) + 2 * ( Machining.dDepthToMachine + ( TOOLS[Machining.nToolIndex].SetupInfo.dZSafeDelta or 60) + EgtMdbGetGeneralParam( MCH_GP.SAFEZ)))
end
else
error( 'GetLengthToMachineAllStepsWithLeadInOut : unknown machining type')
end
return dLengthToMachineAllStepsWithLeadInOut
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.PrepareMachiningsForSorting( Part)
local nFeatureInternalIndex = 1
for i = 1, #MACHININGS do
local MachiningCurrent = MACHININGS[i].Machining
local ProcCurrent = MACHININGS[i].Proc
if not MachiningCurrent.ptCenter then
MachiningCurrent.ptCenter = Point3d( ProcCurrent.b3Box:getCenter():getX(), 0, 0)
end
-- conversione campo sStage in nStage, numerico e ordinabile
if not MachiningCurrent.sStage or MachiningCurrent.sStage == '' then
MachiningCurrent.sStage = 'Middle'
end
if MachiningCurrent.sStage == 'Head' then
MachiningCurrent.nStage = 1
elseif MachiningCurrent.sStage == 'Tail' then
MachiningCurrent.nStage = 3
elseif MachiningCurrent.sStage == 'AfterTail' then
MachiningCurrent.nStage = 4
else
MachiningCurrent.nStage = 2
end
if i > 1 then
local MachiningPrevious = MACHININGS[i - 1].Machining
local ProcPrevious = MACHININGS[i - 1].Proc
if ProcCurrent.id == ProcPrevious.id then
-- nStage devono essere sempre uguali o crescenti nella stessa feature
if MachiningCurrent.nStage < MachiningPrevious.nStage then
MachiningCurrent.nStage = MachiningPrevious.nStage
end
-- assegnazione indice interno alla feature
nFeatureInternalIndex = nFeatureInternalIndex + 1
else
nFeatureInternalIndex = 1
end
end
MachiningCurrent.nFeatureInternalIndex = nFeatureInternalIndex
-- se fase di lavoro standard, assegnazione dello spezzone
if MachiningCurrent.nStage == 2 then
local nParts = #Part.SplittingPoints + 1
if nParts > 1 then
local dPartMinX = Part.b3Part:getMin():getX()
local dPartMaxX = Part.b3Part:getMax():getX()
for j = 1, nParts do
local dNextSplitX = dPartMinX
local dPreviousSplitX = dPartMaxX
if j ~= 1 then
dPreviousSplitX = Part.SplittingPoints[j - 1]:getX()
end
if j ~= nParts then
dNextSplitX = Part.SplittingPoints[j]:getX()
end
if MachiningCurrent.ptCenter:getX() > dNextSplitX - 10 * GEO.EPS_SMALL and MachiningCurrent.ptCenter:getX() < dPreviousSplitX + 10 * GEO.EPS_SMALL then
MachiningCurrent.nPartSegment = j
end
end
else
MachiningCurrent.nPartSegment = -1
end
else
MachiningCurrent.nPartSegment = -1
end
end
return MACHININGS
end
-- TODO nShifts è solo per debug, si può togliere??
-- ripristina l'ordine delle lavorazioni interno alla feature, se non rispettato
-------------------------------------------------------------------------------------------------------------
function MachiningLib.FinalizeSorting()
local nShifts = 0
for i = #MACHININGS, 2, -1 do
for j = i - 1, 1, -1 do
if MACHININGS[i].Proc.id == MACHININGS[j].Proc.id
and MACHININGS[i].Machining.nFeatureInternalIndex < MACHININGS[j].Machining.nFeatureInternalIndex then
MACHININGS[i], MACHININGS[j] = MACHININGS[j], MACHININGS[i]
nShifts = nShifts + 1
end
end
end
return MACHININGS, nShifts
end
-- TODO convertire in tabella in cui si chiamano direttamente i nomi delle funzioni, in modo da poter cambiare l'ordine facilmente
-- TODO libreria Sorting??
-------------------------------------------------------------------------------------------------------------
local SortingComparisonRules = {
-- ordine interno alla feature
function( MachiningA, MachiningB)
if MachiningA.Proc.id == MachiningB.Proc.id then
if MachiningA.Machining.nFeatureInternalIndex < MachiningB.Machining.nFeatureInternalIndex then
return 1
elseif MachiningA.Machining.nFeatureInternalIndex > MachiningB.Machining.nFeatureInternalIndex then
return -1
end
end
return 0
end,
-- dipendenze solo spostamento stage 2->4
-- TODO da fare
-- stage
function( MachiningA, MachiningB)
if MachiningA.Machining.nStage < MachiningB.Machining.nStage then
return 1
elseif MachiningA.Machining.nStage > MachiningB.Machining.nStage then
return -1
else
return 0
end
end,
-- dipendenze
-- TODO da fare
-- segment
function ( MachiningA, MachiningB)
if MachiningA.Machining.nPartSegment < MachiningB.Machining.nPartSegment then
return 1
elseif MachiningA.Machining.nPartSegment > MachiningB.Machining.nPartSegment then
return -1
else
return 0
end
end,
-- testa
-- TODO da fare
-- famiglia utensile
function ( MachiningA, MachiningB)
-- TODO tirare fuori da qua??
local ToolFamilyOrder = {
SAWBLADE = 1,
DRILLBIT = 2,
MILL = 3,
MORTISE = 4
}
local nToolFamilyOrderA = ToolFamilyOrder[ TOOLS[ MachiningA.Machining.nToolIndex].sFamily]
local nToolFamilyOrderB = ToolFamilyOrder[ TOOLS[ MachiningB.Machining.nToolIndex].sFamily]
if nToolFamilyOrderA < nToolFamilyOrderB then
return 1
elseif nToolFamilyOrderA > nToolFamilyOrderB then
return -1
else
return 0
end
end,
-- performance utensile
function( MachiningA, MachiningB)
local dToolPerformanceIndexA = TOOLS[MachiningA.Machining.nToolIndex].dPerformanceIndex
local dToolPerformanceIndexB = TOOLS[MachiningB.Machining.nToolIndex].dPerformanceIndex
if dToolPerformanceIndexA > dToolPerformanceIndexB then
return 1
elseif dToolPerformanceIndexA < dToolPerformanceIndexB then
return -1
else
return 0
end
end,
-- probabilmente arrivati qui significa che gli utensili A e B sono gli stessi
-- se così non fosse e tutte le caratteristiche sopra sono uguali, ordine alfabetico
function( MachiningA, MachiningB)
local sToolNameA = TOOLS[MachiningA.Machining.nToolIndex].sName
local sToolNameB = TOOLS[MachiningB.Machining.nToolIndex].sName
if sToolNameA < sToolNameB then
return 1
elseif sToolNameA > sToolNameB then
return -1
else
return 0
end
end,
-- lato di lavoro
-- TODO questo, insieme all'ordinamento X, andrà sostituito dallo shortest path pesato sulla quantità di rotazione della testa
function( MachiningA, MachiningB)
if MachiningA.Machining.vtToolDirection:getY() < -0.174 and MachiningB.Machining.vtToolDirection:getY() >= 0.174 then
return 1
elseif MachiningA.Machining.vtToolDirection:getY() >= 0.174 and MachiningB.Machining.vtToolDirection:getY() < -0.174 then
return -1
else
return 0
end
end,
-- ordinamento X
-- TODO questo andrà sostituito dallo shortest path pesato sulla quantità di rotazione della testa
function( MachiningA, MachiningB)
local bIsMachiningOnFront = MachiningA.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL
local nResult = 0
-- se lavorazione davanti ordine testa->coda
if bIsMachiningOnFront then
if MachiningA.Machining.ptCenter:getX() > MachiningB.Machining.ptCenter:getX() + 10 * GEO.EPS_SMALL then
nResult = 1
elseif MachiningA.Machining.ptCenter:getX() < MachiningB.Machining.ptCenter:getX() - 10 * GEO.EPS_SMALL then
nResult = -1
end
-- se lavorazione dietro ordine coda->testa
else
if MachiningA.Machining.ptCenter:getX() < MachiningB.Machining.ptCenter:getX() - 10 * GEO.EPS_SMALL then
nResult = 1
elseif MachiningA.Machining.ptCenter:getX() > MachiningB.Machining.ptCenter:getX() + 10 * GEO.EPS_SMALL then
nResult = -1
end
end
return nResult
end
}
-------------------------------------------------------------------------------------------------------------
function MachiningLib.CompareMachinings( MachiningA, MachiningB)
-- itera le SortingComparisonRules una per volta. Se non vi è alcuna scelta va avanti (result = 0), altrimenti ritorna true/false in base al risultato
for i = 1, #SortingComparisonRules do
local CompareFunction = SortingComparisonRules[i]
local result = CompareFunction( MachiningA, MachiningB)
if result ~= 0 then
return result > 0
end
end
return false
end
-------------------------------------------------------------------------------------------------------------
return MachiningLib