268 lines
11 KiB
Lua
268 lines
11 KiB
Lua
-- Strategia: STR0010
|
|
-- Descrizione
|
|
-- fresatura perpendicolare
|
|
-- Feature: cut, longcut, ...
|
|
|
|
-- carico librerie
|
|
local BeamLib = require( 'BeamLib')
|
|
local BeamData = require( 'BeamData')
|
|
local MachiningLib = require( 'MachiningLib')
|
|
local FeatureLib = require( 'FeatureLib')
|
|
-- strategie di base
|
|
local FaceByMill = require('FACEBYMILL')
|
|
|
|
-- Tabella per definizione modulo
|
|
local STR0010 = {}
|
|
local Strategy = {}
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function GetStrategyCompletionPercentage( Machinings)
|
|
local dCompletionPercentage = 0
|
|
|
|
local dCompletionPercentageNumerator = 0
|
|
local dCompletionPercentageDenominator = 0
|
|
local nWeightsCount = 0
|
|
for i = 1, #Machinings do
|
|
local Machining = Machinings[i]
|
|
local dWeight = Machining.dResultWeight
|
|
if not dWeight or ( dWeight < 10 * GEO.EPS_SMALL) then
|
|
dWeight = 1
|
|
else
|
|
nWeightsCount = nWeightsCount + 1
|
|
end
|
|
-- il peso deve essere settato in tutte le lavorazioni o in nessuna
|
|
if nWeightsCount ~= 0 and nWeightsCount ~= i then
|
|
error( 'GetWeightedCompletionPercentage : inconsistent weights')
|
|
end
|
|
local dWeightedCompletionPercentage = Machining.dCompletionPercentage / 100 * dWeight
|
|
if Machining.bIsApplicable then
|
|
dCompletionPercentageNumerator = dCompletionPercentageNumerator + dWeightedCompletionPercentage
|
|
end
|
|
dCompletionPercentageDenominator = dCompletionPercentageDenominator + dWeight
|
|
end
|
|
|
|
dCompletionPercentage = min( 100 * dCompletionPercentageNumerator / dCompletionPercentageDenominator, 100)
|
|
|
|
return dCompletionPercentage
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function CompareEdges( EdgeA, EdgeB)
|
|
-- prima i lati orientati lungo X
|
|
if abs( EdgeA.vtN:getX()) < abs( EdgeB.vtN:getX()) - 10 * GEO.EPS_SMALL then
|
|
return true
|
|
elseif abs( EdgeA.vtN:getX()) > abs( EdgeB.vtN:getX()) + 10 * GEO.EPS_SMALL then
|
|
return false
|
|
-- se stessa X si preferiscono i lati più lunghi (nel caso di 5 lati è quello non spezzato)
|
|
else
|
|
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
|
|
return true
|
|
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
|
|
return false
|
|
-- se stessa lunghezza si preferiscono i lati più in basso
|
|
-- TODO qui dipenderà dalla lama scelta
|
|
else
|
|
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
|
|
return true
|
|
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
|
|
return false
|
|
-- se stessa Z si preferiscono i lati verso il fronte della trave
|
|
else
|
|
if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then
|
|
return true
|
|
elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 10 * GEO.EPS_SMALL then
|
|
return false
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function IsTopologyOk( Proc)
|
|
if Proc.Topology.sFamily == 'Bevel' or Proc.Topology.sFamily == 'DoubleBevel' or
|
|
Proc.Topology.sName == 'VGroove-2-Through' or Proc.Topology.sName == 'Rabbet-2-Through' then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- TODO modificare funzione e verificare pinzaggio con regioni e area outline
|
|
local function IsPositionOK( Proc, Part)
|
|
local bIsFeatureLong = FeatureLib.IsMachiningLong( Proc.b3Box:getDimX(), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
|
|
-- se impatta su faccia retro o sotto, controllo fattibilità
|
|
if Proc.AffectedFaces.bBack then
|
|
if ( bIsFeatureLong and Proc.b3Box:getDimZ() > Part.dHeight / 2) or ( not bIsFeatureLong and Proc.b3Box:getDimZ() > Part.dHeight / 2) then
|
|
return false
|
|
end
|
|
end
|
|
if Proc.AffectedFaces.bBottom then
|
|
if ( bIsFeatureLong and Proc.b3Box:getDimY() > Part.dHeight / 2) or ( not bIsFeatureLong and Proc.b3Box:getDimY() > Part.dHeight / 2) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
-- altrimenti fattibile
|
|
return true
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- TODO da sistemare
|
|
local function GetBottomFaceEdge( Proc, nIndexFace)
|
|
local Edge = {}
|
|
|
|
-- si lavora la bottom longitudinalmente
|
|
if Proc.nFct == 1 or Proc.Topology.sFamily == 'DoubleBevel' then
|
|
local BottomEdgesSorted = {}
|
|
for i = 1, #Proc.MainFaces.BottomFaces[nIndexFace].Edges do
|
|
table.insert( BottomEdgesSorted, Proc.MainFaces.BottomFaces[nIndexFace].Edges[i])
|
|
end
|
|
table.sort( BottomEdgesSorted, CompareEdges)
|
|
Edge = BottomEdgesSorted[1]
|
|
-- edge in comune tra le due facce
|
|
elseif Proc.nFct == 2 then
|
|
if nIndexFace == 1 then
|
|
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.LongEdges[1]
|
|
elseif nIndexFace == 2 then
|
|
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.BottomEdge
|
|
end
|
|
else
|
|
if nIndexFace == 1 then
|
|
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.LongEdges[1]
|
|
elseif nIndexFace == 2 then
|
|
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.BottomEdge
|
|
end
|
|
end
|
|
|
|
return Edge
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function SortMachiningsBySegment( MachiningA, MachiningB)
|
|
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
|
return false
|
|
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
|
return true
|
|
else
|
|
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
|
|
return true
|
|
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
|
|
return false
|
|
else
|
|
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
|
return true
|
|
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
|
|
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
|
|
local StrategyLib = {}
|
|
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
|
|
Strategy.sName = StrategyLib.Config.sStrategyId
|
|
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, CustomParameters, StrategyLib.Config)
|
|
Strategy.Machinings = {}
|
|
Strategy.Result = {}
|
|
|
|
-- controllo su topologia
|
|
if not IsTopologyOk( Proc) then
|
|
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Strategy ' .. StrategyLib.Config.sStrategyId .. ' not implemented')
|
|
return false, Strategy.Result
|
|
end
|
|
|
|
-- controllo dimensioni
|
|
if not IsPositionOK( Proc, Part) then
|
|
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Feature not machinable in this position')
|
|
return false, Strategy.Result
|
|
end
|
|
|
|
-- volume della feature
|
|
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
|
|
|
|
-- TODO taglio su eventuali facce di chiusura
|
|
|
|
-- eventuali punti di spezzatura
|
|
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
|
local bIsSplitFeature = false
|
|
if #FeatureSplittingPoints > 0 then
|
|
bIsSplitFeature = true
|
|
end
|
|
|
|
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
|
|
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
|
|
dExtendAfterTail = 10000
|
|
end
|
|
|
|
-- lavorazione della BottomFace
|
|
local bAreAllMachiningsAdded = true
|
|
local Milling = {}
|
|
local OptionalParametersFaceByMill = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
|
|
local EdgeToMachine = GetBottomFaceEdge( Proc, 1)
|
|
if EdgeToMachine.bIsOpen then
|
|
OptionalParametersFaceByMill.dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA
|
|
end
|
|
Milling = FaceByMill.Make( Proc, Part, Proc.MainFaces.BottomFaces[1], EdgeToMachine, OptionalParametersFaceByMill)
|
|
if Milling.bIsApplicable then
|
|
table.insert( Strategy.Machinings, Milling)
|
|
end
|
|
|
|
-- si lavora seconda BottomFace
|
|
if Proc.Topology.sFamily == 'DoubleBevel' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' then
|
|
local dAngleBetweenFaces = Proc.AdjacencyMatrix[1][2]
|
|
-- se convesso o concavo maggiore di angolo retto
|
|
if dAngleBetweenFaces >= -91 then
|
|
Milling = {}
|
|
OptionalParametersFaceByMill = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
|
|
EdgeToMachine = GetBottomFaceEdge( Proc, 2)
|
|
if EdgeToMachine.bIsOpen then
|
|
OptionalParametersFaceByMill.dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA
|
|
end
|
|
Milling = FaceByMill.Make( Proc, Part, Proc.MainFaces.BottomFaces[2], EdgeToMachine, OptionalParametersFaceByMill)
|
|
if Milling.bIsApplicable then
|
|
table.insert( Strategy.Machinings, Milling)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- calcolo completamento, serve la lista di lavorazioni che comprende le non applicabili
|
|
Strategy.Result.dCompletionPercentage = GetStrategyCompletionPercentage( Strategy.Machinings)
|
|
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
|
|
|
|
Strategy.Machinings = MachiningLib.GetSplitMachinings( Strategy.Machinings, FeatureSplittingPoints, Part)
|
|
table.sort( Strategy.Machinings, SortMachiningsBySegment)
|
|
|
|
Strategy.Result.nQuality = FeatureLib.GetStrategyQuality( Strategy.Machinings)
|
|
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Strategy.Machinings)
|
|
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
|
|
if Strategy.Result.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
|
|
Strategy.Result.sStatus = 'Completed'
|
|
else
|
|
Strategy.Result.sStatus = 'Not-Completed'
|
|
end
|
|
|
|
-- aggiunta lavorazioni
|
|
if #Strategy.Machinings > 0 then
|
|
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
|
|
-- aggiunge lavorazione
|
|
for j = 1, #Strategy.Machinings do
|
|
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machinings[j])
|
|
end
|
|
end
|
|
else
|
|
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
|
|
end
|
|
|
|
return bAreAllMachiningsAdded, Strategy.Result
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
|
|
return STR0010 |