- in BatchProcessNew -> GET_TOPOLOGY si legge anche nParts (serve nel Classify Topology)

- in STR0005 si ammettono feature a più di 3 lati se la topologia è DoubleBevel
- in BLADEKEEPWASTE si gestisce topologia DoubleBevel e migliorie varie
This commit is contained in:
luca.mazzoleni
2026-03-06 12:42:53 +01:00
parent 3e55af917e
commit 7b12eaf331
4 changed files with 179 additions and 136 deletions
+1
View File
@@ -250,6 +250,7 @@ elseif BEAM.FLAG == 9 then
local Proc = FeatureLib.GetProcFromTrimesh( BEAM.FEATUREID, Part)
Proc.nGrp = EgtGetInfo( Proc.id, 'GRP', 'i')
Proc.nPrc = EgtGetInfo( Proc.id, 'PRC', 'i')
Proc.nParts = EgtSurfTmPartCount( Proc.id) or 1
Proc.Topology = {}
if FeatureLib.NeedTopologyFeature( Proc, Part) then
+1 -1
View File
@@ -66,7 +66,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
local dQualityAddedFace = 0
-- più di 3 facce non supportate
if Proc.nFct > 3 then
if Proc.nFct > 3 and ( not Proc.Topology.sFamily == 'DoubleBevel') then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'More than 3 faces not supported')
end
+2 -3
View File
@@ -238,8 +238,9 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
local bAreAllMachiningsAdded = true
-- per prima si lavora sempre la BottomFace (deve avere 4 lati esatti)
-- ricerca delle Bottom (la principale deve avere 4 lati esatti)
local BottomFace1 = Proc.MainFaces.BottomFaces[1]
local BottomFace2 = Proc.MainFaces.BottomFaces[2]
if #BottomFace1.Edges ~= 4 then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
return false, Strategy.Result
@@ -274,7 +275,6 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
table.insert( CalculatedMachinings, Milling1)
-- se necessario si lavora la seconda Bottom (solo se ha 4 lati esatti)
local BottomFace2 = Proc.MainFaces.BottomFaces[2]
local Milling2
local BottomEdgeToMachine2
if BottomFace2 then
@@ -405,7 +405,6 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
end
end
-- calcolo completamento, serve la lista di lavorazioni che comprende le non applicabili
Strategy.Result.dCompletionPercentage = GetStrategyCompletionPercentage( CalculatedMachinings)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
+175 -132
View File
@@ -19,40 +19,57 @@ local FaceByMill = require('FACEBYMILL')
-- tabelle per definizione modulo
-------------------------------------------------------------------------------------------------------------
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
local function CompareEdgesLongestTop( EdgeA, EdgeB)
-- si preferiscono i lati più lunghi
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
return true
elseif abs( EdgeA.vtN:getX()) > abs( EdgeB.vtN:getX()) + 10 * GEO.EPS_SMALL then
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
return false
-- se stessa X si preferiscono i lati più lunghi (nel caso di 5 lati è quello non spezzato)
-- se stessa lunghezza si preferiscono i lati più in basso
else
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
return false
-- se stessa lunghezza si preferiscono i lati più in basso
-- TODO qui dipenderà dalla lama scelta
-- se stessa Z si preferiscono i lati verso il fronte della trave
else
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 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
return false
end
end
end
end
local function GetLongEdgeToMachine( Face, bHeadType)
local Edge = {}
local EdgesSorted = {}
for i = 1, #Face.Edges do
table.insert( EdgesSorted, Face.Edges[i])
end
table.sort( EdgesSorted, CompareEdgesLongestTop)
-- se il lato migliore è accessibile si sceglie questo, altrimenti il lato opposto; se entrambi non accessibili (faccia chiusa da due lati) la lavorazione non è applicabile
Edge = EdgesSorted[1]
local EdgeOpposite = BeamLib.FindEdgeBestOrientedAsDirection( Face.Edges, -Edge.vtN)
if not EdgeOpposite.bIsOpen then
if Edge.bIsOpen then
Edge = EdgeOpposite
-- entrambi i lati non accessibili: codolo non applicabile
else
return nil
end
end
return Edge
end
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
@@ -118,6 +135,76 @@ local function GetStrategyCompletionPercentage( Machinings)
end
local function MakeBottomFace( Proc, Part, BottomFace, EdgeToMachine, Parameters)
local Cuttings = {}
local Cutting1 = {}
local Cutting2 = {}
-- parametri dal chiamante
local bIsSplitFeature = Parameters.bIsSplitFeature
local dExtendAfterTail = Parameters.dExtendAfterTail
local nToolIndex = Parameters.nToolIndex
local dStripWidth = Parameters.dStripWidth
local OtherBottomFace = Parameters.OtherBottomFace
local dDepthToMachine = EdgeToMachine.dElevation / 2 - dStripWidth / 2
local OptionalParametersFaceByBlade1 = { dDepthToMachine = dDepthToMachine, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail, nToolIndex = nToolIndex}
local EdgeToMachineOpposite = BeamLib.FindEdgeBestOrientedAsDirection( BottomFace.Edges, -EdgeToMachine.vtN)
-- primo lato
if EdgeToMachineOpposite.bIsOpen then
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade1)
end
Cutting1.nInternalSortingPriority = 3
Cutting1.dResultWeight = 0.3
-- secondo lato
local OptionalParametersFaceByBlade2 = BeamLib.TableCopyDeep( OptionalParametersFaceByBlade1)
OptionalParametersFaceByBlade2.OppositeToolDirectionMode = 'Enabled'
if EdgeToMachine.bIsOpen then
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade2)
end
Cutting2.nInternalSortingPriority = 3
Cutting2.dResultWeight = 0.3
-- se uno dei due lati non è riuscito, si estende il più possibile il lato rimasto
if not Cutting1.bIsApplicable and Cutting2.bIsApplicable then
-- se si lavora il lato in comune con l'altra BottomFace significa ci si deve fermare piú indietro
if EdgeToMachine.idAdjacentFace == OtherBottomFace.id then
dStripWidth = TOOLS[Cutting2.nToolIndex].dThickness + 2 * dStripWidth
end
dDepthToMachine = min( TOOLS[Cutting2.nToolIndex].dMaxMaterial, EdgeToMachine.dElevation - dStripWidth)
OptionalParametersFaceByBlade2.dDepthToMachine = dDepthToMachine
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade2)
Cutting2.nInternalSortingPriority = 3
Cutting2.dResultWeight = 0.3
table.insert( Cuttings, Cutting2)
elseif not Cutting2.bIsApplicable and Cutting1.bIsApplicable then
-- se si lavora il lato in comune con l'altra BottomFace significa ci si deve fermare piú indietro
if EdgeToMachine.idAdjacentFace == OtherBottomFace.id then
dStripWidth = TOOLS[Cutting1.nToolIndex].dThickness + 2 * dStripWidth
end
dDepthToMachine = min( TOOLS[Cutting1.nToolIndex].dMaxMaterial, EdgeToMachine.dElevation - dStripWidth)
OptionalParametersFaceByBlade1.dDepthToMachine = dDepthToMachine
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade1)
Cutting1.nInternalSortingPriority = 3
Cutting1.dResultWeight = 0.3
table.insert( Cuttings, Cutting1)
else
table.insert( Cuttings, Cutting1)
table.insert( Cuttings, Cutting2)
end
return Cuttings
end
function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
-- TODO verificare funzionamento con lama da sotto
-- TODO scelta utensile è corretto lasciarla a FaceByBlade?
@@ -126,12 +213,11 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
local Result = {}
local Machinings = {}
local CalculatedMachinings = {}
local Cutting1 = {}
local Cutting2 = {}
-- controlli preventivi
if Proc.nFct > 3 then
error( 'BladeKeepWaste : max 3 faces supported')
if Proc.nFct > 3 and ( not Proc.Topology.sFamily == 'DoubleBevel') then
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : max 3 faces supported')
return Machinings, Result
elseif Proc.nFct == 2 then
-- per angolo tra le facce >= 90deg (feature convessa) non applicabile
if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][2] < -91 then
@@ -160,12 +246,7 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
end
local nToolIndex = OptionalParameters.nToolIndex
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
local bFinishWithMill
if OptionalParameters.bFinishWithMill == nil then
bFinishWithMill = true
else
bFinishWithMill = OptionalParameters.bFinishWithMill
end
local bFinishWithMill = ( OptionalParameters.bFinishWithMill ~= false)
local dMillingOffsetFromSide = OptionalParameters.dMillingOffsetFromSide or 1
local dStripWidth = OptionalParameters.dStripWidth or 5
local bForced = OptionalParameters.bForced or false
@@ -173,28 +254,22 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
-- volume della feature
local dFeatureVolume = Proc.dVolume
-- si trovano le facce da lavorare
local BottomFace = {}
local LongFaces = {}
-- si trovano le facce da lavorare (solo 4 lati esatti)
local BottomFace1
local BottomFace2
if Proc.nFct == 1 then
BottomFace = Proc.Faces[1]
BottomFace1 = Proc.Faces[1]
else
if not Proc.MainFaces then
Proc.MainFaces = FaceData.GetMainFaces( Proc, Part)
end
BottomFace = Proc.MainFaces.BottomFaces[1]
LongFaces = Proc.MainFaces.LongFaces
BottomFace1 = Proc.MainFaces.BottomFaces[1]
BottomFace2 = Proc.MainFaces.BottomFaces[2]
end
-- si trova il lato della faccia di fondo da lavorare
local BottomEdgeToMachine = {}
local BottomEdgesSorted = {}
for i = 1, #BottomFace.Edges do
table.insert( BottomEdgesSorted, BottomFace.Edges[i])
if #BottomFace1.Edges ~= 4 then
Result = FeatureLib.GetStrategyResultNotApplicable()
return Machinings, Result
end
table.sort( BottomEdgesSorted, CompareEdges)
BottomEdgeToMachine = BottomEdgesSorted[1]
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
@@ -203,98 +278,66 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
bIsSplitFeature = true
end
-- calcolo lavorazioni
-- taglio eventuali facce di chiusura o seconda faccia
for i = 1, #LongFaces do
local Cutting = {}
local OptionalParametersFaceByBlade = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail, nToolIndex = nToolIndex}
Cutting = FaceByBlade.Make( Proc, Part, LongFaces[i], LongFaces[i].MainEdges.BottomEdge, OptionalParametersFaceByBlade)
Cutting.nInternalSortingPriority = 1
Cutting.dResultWeight = 0.15
table.insert( CalculatedMachinings, Cutting)
end
-- taglio con codolo faccia di fondo; si provano solo i lati a cui si può accedere (lato opposto aperto)
-- TODO il check del lato opposto aperto andrà messo nella FaceByBlade
-- TODO verificare se il calcolo del completamento (aggiunta lavorazioni applicabili/non) é corretto
local dDepthToMachine = BottomEdgeToMachine.dElevation / 2 - dStripWidth / 2
local OptionalParametersFaceByBlade1 = { dDepthToMachine = dDepthToMachine, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail, nToolIndex = nToolIndex}
local BottomEdgeToMachineOpposite = BeamLib.FindEdgeBestOrientedAsDirection( BottomFace.Edges, -BottomEdgeToMachine.vtN)
-- primo lato
if BottomEdgeToMachineOpposite.bIsOpen then
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade1)
end
Cutting1.nInternalSortingPriority = 3
Cutting1.dResultWeight = 0.3
-- secondo lato
local OptionalParametersFaceByBlade2 = BeamLib.TableCopyDeep( OptionalParametersFaceByBlade1)
OptionalParametersFaceByBlade2.OppositeToolDirectionMode = 'Enabled'
if BottomEdgeToMachine.bIsOpen then
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade2)
end
Cutting2.nInternalSortingPriority = 3
Cutting2.dResultWeight = 0.3
-- se uno dei due lati non è riuscito, si estende il più possibile il lato rimasto
if not Cutting1.bIsApplicable and Cutting2.bIsApplicable then
-- se si lavora il lato in comune con la LongFace significa che la LongFace non é di chiusura ma un'altra faccia vera e propria
-- ci si deve quindi fermare piú indietro
for i = 1, #LongFaces do
if BottomEdgeToMachine.idAdjacentFace == LongFaces[i].id then
dStripWidth = TOOLS[Cutting2.nToolIndex].dThickness + 2 * dStripWidth
break
end
end
dDepthToMachine = min( TOOLS[Cutting2.nToolIndex].dMaxMaterial, BottomEdgeToMachine.dElevation - dStripWidth)
OptionalParametersFaceByBlade2.dDepthToMachine = dDepthToMachine
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade2)
Cutting2.nInternalSortingPriority = 3
Cutting2.dResultWeight = 0.3
table.insert( CalculatedMachinings, Cutting2)
elseif not Cutting2.bIsApplicable and Cutting1.bIsApplicable then
-- se si lavora il lato in comune con la LongFace significa che la LongFace non é di chiusura ma un'altra faccia vera e propria
-- ci si deve quindi fermare piú indietro
for i = 1, #LongFaces do
if BottomEdgeToMachine.idAdjacentFace == LongFaces[i].id then
dStripWidth = TOOLS[Cutting1.nToolIndex].dThickness + 2 * dStripWidth
break
end
end
dDepthToMachine = min( TOOLS[Cutting1.nToolIndex].dMaxMaterial, BottomEdgeToMachine.dElevation - dStripWidth)
OptionalParametersFaceByBlade1.dDepthToMachine = dDepthToMachine
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade1)
Cutting1.nInternalSortingPriority = 3
Cutting1.dResultWeight = 0.3
table.insert( CalculatedMachinings, Cutting1)
else
table.insert( CalculatedMachinings, Cutting1)
table.insert( CalculatedMachinings, Cutting2)
-- calcolo lavorazioni faccia principale
-- ricerca lato da lavorare
local BottomEdgeToMachine1 = GetLongEdgeToMachine( BottomFace1, { bTop = true})
-- calcolo lavorazione
local Parameters1 = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
nToolIndex = nToolIndex,
dStripWidth = dStripWidth,
OtherBottomFace = BottomFace2
}
local Cuttings1 = MakeBottomFace( Proc, Part, BottomFace1, BottomEdgeToMachine1, Parameters1)
-- aggiunta lavorazioni alla lista principale
for i = 1, #Cuttings1 do
table.insert( CalculatedMachinings, Cuttings1[i])
end
-- fresatura eventuali facce di chiusura
if bFinishWithMill then
for i = 1, #LongFaces do
if BottomEdgeToMachine.idAdjacentFace ~= LongFaces[i].id then
local dDepthToMachineMill = BottomFace.MainEdges.LongEdges[i].dElevation - dMillingOffsetFromSide
local dToolMarkLength = max( Cutting1.dToolMarkLength or 0, Cutting2.dToolMarkLength or 0)
local OptionalParametersFaceByMill = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail,
dRadialStepSpan = dToolMarkLength, dDepthToMachine = dDepthToMachineMill
}
local Milling = FaceByMill.Make( Proc, Part, BottomFace, BottomFace.MainEdges.LongEdges[i], OptionalParametersFaceByMill)
Milling.nInternalSortingPriority = 2
Milling.dResultWeight = 0.05
table.insert( CalculatedMachinings, Milling)
end
-- calcolo lavorazioni faccia secondaria, solo se lato convesso; se concavo, sarà lavorato come antisplint
local Cuttings2
local bConvexAngle = ( Proc.AdjacencyMatrix[BottomFace1.id + 1][BottomFace2.id + 1]) > 0
if BottomFace2 and bConvexAngle then
-- ricerca lato da lavorare
local BottomEdgeToMachine2 = GetLongEdgeToMachine( BottomFace2, { bTop = true})
-- calcolo lavorazione
local Parameters2 = BeamLib.TableCopyDeep( Parameters1)
Parameters2.OtherBottomFace = BottomFace1
Cuttings2 = MakeBottomFace( Proc, Part, BottomFace2, BottomEdgeToMachine2, Parameters2)
for i = 1, #Cuttings2 do
table.insert( CalculatedMachinings, Cuttings2[i])
end
end
-- -- taglio eventuali facce di chiusura o seconda faccia
-- for i = 1, #LongFaces do
-- local Cutting = {}
-- local OptionalParametersFaceByBlade = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail, nToolIndex = nToolIndex}
-- Cutting = FaceByBlade.Make( Proc, Part, LongFaces[i], LongFaces[i].MainEdges.BottomEdge, OptionalParametersFaceByBlade)
-- Cutting.nInternalSortingPriority = 1
-- Cutting.dResultWeight = 0.15
-- table.insert( CalculatedMachinings, Cutting)
-- end
-- -- fresatura eventuali facce di chiusura
-- if bFinishWithMill then
-- for i = 1, #LongFaces do
-- if BottomEdgeToMachine.idAdjacentFace ~= LongFaces[i].id then
-- local dDepthToMachineMill = BottomFace1.MainEdges.LongEdges[i].dElevation - dMillingOffsetFromSide
-- local dToolMarkLength = max( Cutting1.dToolMarkLength or 0, Cutting2.dToolMarkLength or 0)
-- local OptionalParametersFaceByMill = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail,
-- dRadialStepSpan = dToolMarkLength, dDepthToMachine = dDepthToMachineMill
-- }
-- local Milling = FaceByMill.Make( Proc, Part, BottomFace1, BottomFace1.MainEdges.LongEdges[i], OptionalParametersFaceByMill)
-- Milling.nInternalSortingPriority = 2
-- Milling.dResultWeight = 0.05
-- table.insert( CalculatedMachinings, Milling)
-- end
-- end
-- end
-- lavorazioni da applicare spostate in lista finale
for i = 1, #CalculatedMachinings do
if CalculatedMachinings[i].bIsApplicable then
@@ -317,7 +360,7 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
table.sort( Machinings, SortMachiningsBySegment)
-- calcolo risultati
if Cutting1.bIsApplicable or Cutting2.bIsApplicable then
if Cuttings1[1].bIsApplicable or Cuttings1[2].bIsApplicable then
Result.dQuality = FeatureLib.GetStrategyQuality( Machinings)
Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Machinings)
Result.dMRR = ( dFeatureVolume / Result.dTimeToMachine) / pow( 10, 6)