936 lines
43 KiB
Lua
936 lines
43 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)
|
|
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
|
|
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 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 = ''
|
|
end
|
|
Machinings[nCurrentMachiningIndex].nFeatureSegment = 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 = 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
|
|
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].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
|
|
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].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex 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.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
|
|
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
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
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
|
|
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()
|
|
elseif 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
|
|
end
|
|
|
|
return MACHININGS
|
|
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() < 10 * GEO.EPS_SMALL and MachiningB.Machining.vtToolDirection:getY() >= 10 * GEO.EPS_SMALL then
|
|
return 1
|
|
elseif MachiningA.Machining.vtToolDirection:getY() >= 10 * GEO.EPS_SMALL and MachiningB.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL 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
|