From 665113929a81fa8d1482b3597b0e6bf22a191267 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Wed, 29 Jan 2025 10:18:37 +0100 Subject: [PATCH 1/9] - in FACEBYBLADE aggiunta scrittura del frame lavorazione vtFaceUse - picoole migliorie varie --- LuaLibs/MachiningLib.lua | 3 ++- Strategies/Standard/HEADCUT/HEADCUT.lua | 25 +------------------------ Strategies/Standard/STR0005/STR0005.lua | 12 +++++++++--- StrategyLibs/FACEBYBLADE.lua | 22 ++++++++++++---------- StrategyLibs/FACEBYCHAINSAW.lua | 2 +- StrategyLibs/SPLITCUT.lua | 23 ----------------------- 6 files changed, 25 insertions(+), 62 deletions(-) diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index a9a4417..5b9d0fb 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -542,7 +542,8 @@ function MachiningLib.AddOperations( vProc, Part, sRotation) { sName = 'dStartZmax', sMchParam = 'StartZmax'}, { sName = 'nOutRaw', sMchParam = 'OutRaw'}, { sName = 'nOpenOutRaw', sMchParam = 'OpenOutRaw'}, - { sName = 'nPlunge', sMchParam = 'Plunge'} + { sName = 'nPlunge', sMchParam = 'Plunge'}, + { sName = 'vtFaceUse', sMchParam = 'VtFaceUse'} } -- parametri da scrivere nelle note di sistema diff --git a/Strategies/Standard/HEADCUT/HEADCUT.lua b/Strategies/Standard/HEADCUT/HEADCUT.lua index cc79320..d689743 100644 --- a/Strategies/Standard/HEADCUT/HEADCUT.lua +++ b/Strategies/Standard/HEADCUT/HEADCUT.lua @@ -34,32 +34,9 @@ local function LoadStrategyParameters( CustomParameters) return Strategy end -------------------------------------------------------------------------------------------------------------- -local function CalculateLeadInOut( Machining, EdgeToMachine) - - local LeadIn = {} - local LeadOut = {} - LeadIn.dStartAddLength = 0 - LeadOut.dEndAddLength = 0 - LeadIn.nType = MCH_MILL_LI.LINEAR - LeadOut.nType = MCH_MILL_LI.LINEAR - LeadIn.dTangentDistance = 0 - LeadOut.dTangentDistance = 0 - LeadIn.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation - LeadOut.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation - LeadIn.dElevation = 0 - LeadOut.dElevation = 0 - LeadIn.dCompLength = 0 - LeadOut.dCompLength = 0 - LeadIn.dStartAddLength = BeamData.CUT_EXTRA - LeadOut.dEndAddLength = BeamData.CUT_EXTRA - - return LeadIn, LeadOut -end - ------------------------------------------------------------------------------------------------------------- local function MakeChamfer() - -- TODO funzionalit� da aggiungere + -- TODO funzionalità da aggiungere end ------------------------------------------------------------------------------------------------------------- diff --git a/Strategies/Standard/STR0005/STR0005.lua b/Strategies/Standard/STR0005/STR0005.lua index 311bee6..34ceda8 100644 --- a/Strategies/Standard/STR0005/STR0005.lua +++ b/Strategies/Standard/STR0005/STR0005.lua @@ -114,6 +114,8 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) Strategy.Result = {} Strategy.Result.sInfo = '' Blade.Result = {} + local Cutting = {} + local dMRRBlade = 0 -- estensione oltre la coda local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0) @@ -121,12 +123,12 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) dExtendAfterTail = 10000 end + -- considerazione necessarie a determinare se lasciare il legno attaccato oppure no local dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( Proc, Part) local bLeaveWasteAttached = Strategy.Parameters.sCuttingStrategy == 'LEAVE_WASTE_ATTACHED' local bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN}) - local Cutting = {} - local dMRRBlade = 0 + -- lavorazione con codolo if bFeatureHindersClamping or bLeaveWasteAttached then -- TODO valutare se estrapolare in funzione a sè stante in StrategyLibs -- TODO verificare funzionamento con lama da sotto @@ -152,6 +154,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) bIsSplitFeature = true end + -- calcolo lavorazioni -- primo lato local OptionalParameters = { dDepthToMachine = dDepthToMachine, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail} Cutting1 = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgesSorted[1], OptionalParameters) @@ -173,9 +176,10 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, FeatureSplittingPoints, Part) end + -- ordinamento table.sort( Blade.Result.Sorted, SortMachiningsBySegment) - -- parametri per il calcolo della velocità di asportazione + -- calcolo parametri per la stima della velocità di asportazione MRRParameters1 = { dStep = TOOLS[Cutting1.nToolIndex].dThickness, dSideStep = min( TOOLS[Cutting1.nToolIndex].dSideStep, dDepthToMachine), @@ -191,9 +195,11 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) dMRRBlade = ( dMRRBlade1 + dMRRBlade2) / 2 Cutting = Cutting2 + -- se la lavorazione con codolo fallisce o non è possibile si proseguirà a quella con cubetti end + -- lavorazione a cubetti / taglio singolo if #Blade.Result == 0 and not bLeaveWasteAttached then -- BladeToWaste end diff --git a/StrategyLibs/FACEBYBLADE.lua b/StrategyLibs/FACEBYBLADE.lua index 3c91c15..5ed89eb 100644 --- a/StrategyLibs/FACEBYBLADE.lua +++ b/StrategyLibs/FACEBYBLADE.lua @@ -65,18 +65,18 @@ end local function GetSCC( vtMachiningDirection) -- TODO implementare SCC come per FacesBySaw local nSCC = MCH_SCC.NONE - if AreSameVectorApprox( vtMachiningDirection, Z_AX()) then - nSCC = MCH_SCC.ADIR_ZP - elseif AreOppositeVectorApprox( vtMachiningDirection, Z_AX()) then + if vtMachiningDirection:getZ() < -0.9 then nSCC = MCH_SCC.ADIR_ZM - elseif AreSameVectorApprox( vtMachiningDirection, Y_AX()) then - nSCC = MCH_SCC.ADIR_YP - elseif AreOppositeVectorApprox( vtMachiningDirection, Y_AX()) then + elseif vtMachiningDirection:getZ() > 0.9 then + nSCC = MCH_SCC.ADIR_ZP + elseif vtMachiningDirection:getY() < -0.707 then nSCC = MCH_SCC.ADIR_YM - elseif AreSameVectorApprox( vtMachiningDirection, X_AX()) then - nSCC = MCH_SCC.ADIR_XP - elseif AreOppositeVectorApprox( vtMachiningDirection, X_AX()) then + elseif vtMachiningDirection:getY() > 0.707 then + nSCC = MCH_SCC.ADIR_YP + elseif vtMachiningDirection:getX() < -0.707 then nSCC = MCH_SCC.ADIR_XM + elseif vtMachiningDirection:getX() > 0.707 then + nSCC = MCH_SCC.ADIR_XP end return nSCC @@ -226,11 +226,13 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar Cutting.dStartSafetyLength = 10 -- overlap Cutting.dOverlap = 0 - -- faceuse + -- faceuse e frame lavorazione if bOppositeToolDirection then Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -Cutting.vtToolDirection) + Cutting.vtFaceUse = -Cutting.vtToolDirection else Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( Cutting.vtToolDirection) + Cutting.vtFaceUse = Cutting.vtToolDirection end -- SCC Cutting.nSCC = GetSCC( Cutting.vtToolDirection) diff --git a/StrategyLibs/FACEBYCHAINSAW.lua b/StrategyLibs/FACEBYCHAINSAW.lua index facf6f8..bf1b28a 100644 --- a/StrategyLibs/FACEBYCHAINSAW.lua +++ b/StrategyLibs/FACEBYCHAINSAW.lua @@ -140,7 +140,7 @@ function FACEBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional -- parametri della lavorazione -- TODO gestire ToolInvert per rispettare direzione migliore di lavorazione -- profondità (parametro DEPTH) non usata - Mortising.sDepth = 'TH' + Mortising.sDepth = sDepth -- inizio e fine aperti o chiusi Mortising.bIsStartClosed = not EdgeToMachine.bIsStartOpen Mortising.bIsEndClosed = not EdgeToMachine.bIsEndOpen diff --git a/StrategyLibs/SPLITCUT.lua b/StrategyLibs/SPLITCUT.lua index 2116432..bc71238 100644 --- a/StrategyLibs/SPLITCUT.lua +++ b/StrategyLibs/SPLITCUT.lua @@ -192,29 +192,6 @@ function SPLITCUT.GetEdgeToMachine( Proc, vtEdge) return Edge end -------------------------------------------------------------------------------------------------------------- -function SPLITCUT.CalculateLeadInOut( EdgeToMachine) - - local LeadIn = {} - local LeadOut = {} - LeadIn.dStartAddLength = 0 - LeadOut.dEndAddLength = 0 - LeadIn.nType = MCH_MILL_LI.LINEAR - LeadOut.nType = MCH_MILL_LI.LINEAR - LeadIn.dTangentDistance = 0 - LeadOut.dTangentDistance = 0 - LeadIn.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation - LeadOut.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation - LeadIn.dElevation = 0 - LeadOut.dElevation = 0 - LeadIn.dCompLength = 0 - LeadOut.dCompLength = 0 - LeadIn.dStartAddLength = BeamData.CUT_EXTRA - LeadOut.dEndAddLength = BeamData.CUT_EXTRA - - return LeadIn, LeadOut -end - ----------------------------------------------------------------------------------- function SPLITCUT.Execute( Proc, Part, Strategy) local Machinings = {} From a7664d574379ff304e234a61adab237b66fc5d12 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Wed, 29 Jan 2025 16:31:49 +0100 Subject: [PATCH 2/9] - in DiceCut refactoring --- LuaLibs/DiceCut.lua | 101 +++++++++++++++++----------------- StrategyLibs/BLADETOWASTE.lua | 37 ++++++++++++- 2 files changed, 84 insertions(+), 54 deletions(-) diff --git a/LuaLibs/DiceCut.lua b/LuaLibs/DiceCut.lua index 0b5a02d..8601d51 100644 --- a/LuaLibs/DiceCut.lua +++ b/LuaLibs/DiceCut.lua @@ -134,7 +134,7 @@ end -- vtO: il versore dei piani ortogonali -- dOffsetEff: offset della distanza dal punto centrale -- Verifica se l'asse X del box costruito sopra la superficie è più grande di un certo offset -local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff, dNzLimDwnUp) +local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff, dNzLimDownUp) local FrameLocal = Frame3d( EgtSurfTmFacetCenter( FacetId, 0, GDB_ID.ROOT)) EgtSetGridFrame(FrameLocal) local IdAuxLocal = EgtGroup(EgtGetParent( FacetId), FrameLocal) @@ -155,7 +155,7 @@ local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff, dNzLimDwnUp -- se faccia non troppo lunga, con un lato piccolo e non diretta troppo verso il basso, non servono dice local dMaxLen = BeamData.MAX_LEN_DICE or 600 if dLen < dMaxLen and dWidth < dMaxLen and - ( dLen < dOffsetEff + 1.0 or dWidth < dOffsetEff + 1.0) and vtN:getZ() > dNzLimDwnUp then + ( dLen < dOffsetEff + 1.0 or dWidth < dOffsetEff + 1.0) and vtN:getZ() > dNzLimDownUp then return nil, nil, nil end @@ -257,10 +257,10 @@ end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- VerifyFirstOrthoCut : -- CutTable: tabella dei tagli --- OffsetP: offset della distanza dal punto centrale +-- dOffsetParallel: offset della distanza dal punto centrale -- b3BoxToDicing: il grezzo della barra -- Verifica se l'asse X del box costruito sopra le 2 facce è più piccolo di un certo offset e quindi la faccia O è superflua -local function VerifyFirstOrthoCut( CutTable, OffsetP, b3BoxToDicing, dNzLimDwnUp) +local function VerifyFirstOrthoCut( CutTable, dOffsetParallel, b3BoxToDicing, dNzLimDownUp) if not CutTable[1] or not CutTable[2] then return end @@ -293,7 +293,7 @@ local function VerifyFirstOrthoCut( CutTable, OffsetP, b3BoxToDicing, dNzLimDwnU -- lunghezza totale faccia local dLongSize = x1 + x2 -- se faccia piccola e non orientata verso il basso, elimino ortogonale e unisco le due parti - if dLongSize <= OffsetP + 1.0 and vtN1:getZ() > dNzLimDwnUp then + if dLongSize <= dOffsetParallel + 1.0 and vtN1:getZ() > dNzLimDownUp then local nAddGrpId = EgtGetParent( Cut1Id) local SurfId = EgtSurfTmBySewing( nAddGrpId, { Cut1Id, Cut2Id}) EgtSetColor( SurfId, Color3d( FUCHSIA(), 60)) @@ -392,25 +392,20 @@ end -- OptionaParameters : eventuali parametri opzionali --------------------------------------------------------------------------------------------------------------- function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) - - local dMaxDimDice = BeamData.MAX_DIM_DICE - local dTolerance = 0 -- distanza di sicurezza per i tagli ortogonali - local OffsetP = dMaxDimDice -- distanza tra i piani paralleli - local StepP = 100 -- numero massimo di piani paralleli da generare - local OffsetO = dMaxDimDice -- distanza tra i piani ortogonali - local StepO = 100 -- numero massimo di piani ortogonali da generare - - -- recupero gruppo per geometria addizionale + -- gruppo per geometria addizionale local nAddGrpId = BeamLib.GetAddGroup( Part.id) - -- se il box non è passato tra i parametri opzionali, faccio i calcoli sul SOLID del Part - local b3BoxToDicing = OptionalParameters.b3BoxToDicing or Part.b3Part - -- copio dati passati su variabili locali - local ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, bGetOrtoPlanes + + -- faccia primaria + local ptCMainFace + local vtNMainFace if Face1.ptCenter and Face1.vtNormal then ptCMainFace = Face1.ptCenter vtNMainFace = Face1.vtNormal end - -- se esiste faccia secondaria non esiste, forzo calcolo piani ortogonali + -- faccia secondaria; se non esiste, si forza il calcolo dei piani ortogonali + local ptCSubordinateFace + local vtNSubordinateFace + local bGetOrtoPlanes if Face2.ptCenter and Face2.vtNormal then ptCSubordinateFace = Face2.ptCenter vtNSubordinateFace = Face2.vtNormal @@ -418,48 +413,52 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) else bGetOrtoPlanes = true end - -- ricavo dimensione massima cubetti - if OptionalParameters.dCustMaxDimDice and OptionalParameters.dCustMaxDimDice < BeamData.MAX_DIM_DICE then - dMaxDimDice = abs( OptionalParameters.dCustMaxDimDice) - end + + -- parametri opzionali + -- box per dicing + local b3BoxDicing = OptionalParameters.b3BoxDicing or Part.b3Part + -- distanza tra piani paralleli + local dOffsetParallel = OptionalParameters.dOffsetParallel or BeamData.MAX_DIM_DICE + -- distanza tra piani ortogonali + local dOffsetOrthogonal = OptionalParameters.dOffsetOrthogonal or BeamData.MAX_DIM_DICE + -- numero massimo piani paralleli + local nStepParallel = OptionalParameters.nStepParallel or 100 + -- numero massimo piani perpendicolari + local nStepOrthogonal = OptionalParameters.nStepOrthogonal or 100 + -- distanza tra piani paralleli e piani di taglio (era sempre 0, serve???) + local dTolerance = OptionalParameters.dTolerance or 0 + -- inclinazione limite per taglio da sotto + local dNzLimDownUp = OptionalParameters.dNzLimDownUp BeamLib.GetNzLimDownUp( b3BoxDicing) --Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo - local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxToDicing) + local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxDicing) TBoxPoint = VerificaEstremiGrezzo( ptCMainFace, vtNMainFace, TBoxPoint) if ptCSubordinateFace and vtNSubordinateFace then TBoxPoint = VerificaEstremiGrezzo( ptCSubordinateFace, vtNSubordinateFace, TBoxPoint) end - local dElevP = DistanzaMassima( nAddGrpId, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxToDicing, TBoxPoint) + local dElevP = DistanzaMassima( nAddGrpId, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxDicing, TBoxPoint) local dElevO if ptCSubordinateFace and vtNSubordinateFace and not AreOppositeVectorApprox( vtNSubordinateFace, vtNMainFace) then - dElevO = DistanzaMassima( nAddGrpId, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxToDicing, TBoxPoint) - end - - -- inclinazione limite per taglio da sotto - local dNzLimDwnUp = BeamLib.GetNzLimDownUp( b3BoxToDicing) - - -- se non c'è testa da sotto e normali senza componenti in Y con faccia quasi verticale e trave non alta, uso per offset i limiti dei tagli di testa e coda - if not BeamData.DOWN_HEAD and abs( vtNMainFace:getY()) < 0.1 and vtNMainFace:getZ() < 0.7071 and ( not vtNSubordinateFace or abs( vtNSubordinateFace:getY()) < 0.1) and b3BoxToDicing:getDimZ() < BeamData.MIN_DIM_HBEAM then - OffsetO = OptionalParameters.dOrthoMaxDim or BeamData.MAX_DIM_HTCUT + dElevO = DistanzaMassima( nAddGrpId, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxDicing, TBoxPoint) end -- aggiungo piccolo extra agli offset - OffsetP = OffsetP + 10 * GEO.EPS_SMALL - OffsetO = OffsetO + 10 * GEO.EPS_SMALL + dOffsetParallel = dOffsetParallel + 10 * GEO.EPS_SMALL + dOffsetOrthogonal = dOffsetOrthogonal + 10 * GEO.EPS_SMALL -- se piani non ortogonali, diminuisco la distanza di offset opportunamente - local originalOffsetP = OffsetP + local dOffsetParallelOriginal = dOffsetParallel if not bGetOrtoPlanes then local dCoeff = ( vtNMainFace ^ vtNSubordinateFace):len() - OffsetP = OffsetP * dCoeff - OffsetO = OffsetO * dCoeff + dOffsetParallel = dOffsetParallel * dCoeff + dOffsetOrthogonal = dOffsetOrthogonal * dCoeff end - local n = ceil( dElevP / OffsetP) - OffsetP = dElevP / n + local n = ceil( dElevP / dOffsetParallel) + dOffsetParallel = dElevP / n if dElevO then - local m = ceil( dElevO / OffsetO) - OffsetO = dElevO / m + local m = ceil( dElevO / dOffsetOrthogonal) + dOffsetOrthogonal = dElevO / m end -- elenco di tutte le superfici generate dai tagli @@ -468,7 +467,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) -- PIANI PARALLELI alla faccia di taglio local TabellaTmSurfP = {} - local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCMainFace, vtNMainFace, 0, OffsetP, StepP, Color3d( FUCHSIA(), 60), dTolerance, true, ptCSubordinateFace, vtNSubordinateFace) + local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCMainFace, vtNMainFace, 0, dOffsetParallel, nStepParallel, Color3d( FUCHSIA(), 60), dTolerance, true, ptCSubordinateFace, vtNSubordinateFace) for i = #TabFromIn, 1, -1 do table.insert( TabellaTmSurfP, TabFromIn[i]) end @@ -477,7 +476,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) -- orientamento definito da seconda faccia if not bGetOrtoPlanes then local TabellaTmSurfOrto = {} - local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCSubordinateFace, vtNSubordinateFace, 0, OffsetO, StepO, Color3d( GREEN(), 60), dTolerance, false, ptCMainFace, vtNMainFace) + local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCSubordinateFace, vtNSubordinateFace, 0, dOffsetOrthogonal, nStepOrthogonal, Color3d( GREEN(), 60), dTolerance, false, ptCMainFace, vtNMainFace) for i = #TabFromIn, 1, -1 do table.insert( TabellaTmSurfOrto, TabFromIn[i]) end @@ -500,10 +499,10 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) end -- calcolo la direzione dei piani ortogonali local vtO = VectorFromUprightOrtho( vtNInner) - if vtNInner:getZ() > -0.0175 or vtNInner:getZ() < dNzLimDwnUp or abs( vtNInner:getY()) > 0.8 then + if vtNInner:getZ() > -0.0175 or vtNInner:getZ() < dNzLimDownUp or abs( vtNInner:getY()) > 0.8 then vtO:rotate( vtNInner, 90) -- se diretto troppo ortogonalmente all'asse trave e taglio non da sotto, lo ruoto ulteriormente - if ( abs( vtO:getY()) > 4 * abs( vtO:getX()) or b3BoxToDicing:getDimZ() > 620) and vtNInner:getZ() > dNzLimDwnUp then + if ( abs( vtO:getY()) > 4 * abs( vtO:getX()) or b3BoxDicing:getDimZ() > 620) and vtNInner:getZ() > dNzLimDownUp then vtO:rotate( vtNInner, 90) -- se faccia principale verso il basso (almeno -3deg), lo inverto per iniziare da sopra if vtNInner:getZ() < -0.05 then @@ -529,16 +528,16 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) -- CopyPlane: 0 => crea la prima faccia direttamente sul punto passato -- CopyPlane: 1 => crea la prima faccia e tutte le altre con l'offset passato -- CopyPlane: 0.5 => crea la prima faccia a metà offset e tutte le altre con l'offest intero - local OffsetRel, CopyPlane, dCenOffs, ptCStart = GetOrtoCutCenter( TabellaTmSurfP[PlnInd], ptCInner, vtNInner, vtO, OffsetO, dNzLimDwnUp) + local OffsetRel, CopyPlane, dCenOffs, ptCStart = GetOrtoCutCenter( TabellaTmSurfP[PlnInd], ptCInner, vtNInner, vtO, dOffsetOrthogonal, dNzLimDownUp) if OffsetRel and CopyPlane and dCenOffs then ptCInner = ptCInner + dCenOffs * vtO - local TabRight = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCStart, vtO, CopyPlane, -OffsetRel, StepO, Color3d( GREEN(), 60), + local TabRight = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCStart, vtO, CopyPlane, -OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60), dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter) if CopyPlane == 0 then CopyPlane = 1 end - local TabLeft = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCStart, vtO, CopyPlane, OffsetRel, StepO, Color3d( GREEN(), 60), + local TabLeft = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCStart, vtO, CopyPlane, OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60), dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter) -- carico la tabella con gli indici riordinati local TempOrtoTab = {} @@ -578,7 +577,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) -- Se esiste la superficie limitante (nFacet == 2) verifica se il taglio più esterno è superfluo e quindi viene eliminato if not bGetOrtoPlanes then - VerifyFirstOrthoCut( UltimateTable, originalOffsetP, b3BoxToDicing, dNzLimDwnUp) + VerifyFirstOrthoCut( UltimateTable, dOffsetParallelOriginal, b3BoxDicing, dNzLimDownUp) -- se rimangono due sole facce, devono coincidere con le originali e quindi sono superflue if #UltimateTable == 2 and #UltimateTable[1] == 1 and #UltimateTable[2] == 1 then EgtErase( UltimateTable[1][1]) diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index 2926b65..5bb6f17 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -16,11 +16,42 @@ local FaceByBlade = require('FACEBYBLADE') EgtOutLog( ' BLADETOWASTE started', 1) +------------------------------------------------------------------------------------------------------------- - - +function BLADETOWASTE.Make( ) -- if dFeatureVolume < StrategyParameters.dMaxWasteVolume + 10 * GEO.EPS_SMALL -- and dFeatureMaxDimension < StrategyParameters.dMaxWasteLength + 10 * GEO.EPS_SMALL then --- end \ No newline at end of file +-- end + + + + + + + + + + + + + + + + + + + + + + + + + + +end + +------------------------------------------------------------------------------------------------------------- + +return BLADETOWASTE \ No newline at end of file From b8a694db6014cee4df06355626affff62fa45126 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Thu, 30 Jan 2025 09:22:16 +0100 Subject: [PATCH 3/9] - in DiceCut alcune modifiche nomi variabili --- LuaLibs/DiceCut.lua | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/LuaLibs/DiceCut.lua b/LuaLibs/DiceCut.lua index 8601d51..e8447cf 100644 --- a/LuaLibs/DiceCut.lua +++ b/LuaLibs/DiceCut.lua @@ -17,7 +17,7 @@ local BeamData = require( 'BeamData') -- creo i piani paralleli -- GetParallelPlanes: restituisce un vettore con gli indici delle superfici -- nAddGrpId: il layer --- b3BoxToDicing: il grezzo della barra +-- b3BoxDicing: il grezzo della barra -- ptC: il punto centrale del piano della feature -- vtN: il versore normale del piano della feature -- nCopyPlane: 0 => genera una copia del piano passato, 1=> non genera una copia del piano passato @@ -30,7 +30,7 @@ local BeamData = require( 'BeamData') -- vtNCut*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) -- ptCCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) -- vtNCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso) -local function GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptC, vtN, nCopyPlane, dOffset, nStep, Color, dTolerance, bNoTolOnFirstCut, ptCCut, vtNCut, ptCCut1, vtNCut1 ) +local function GetParallelPlanes( nAddGrpId, b3BoxDicing, ptC, vtN, nCopyPlane, dOffset, nStep, Color, dTolerance, bNoTolOnFirstCut, ptCCut, vtNCut, ptCCut1, vtNCut1 ) local ptMyCCut local AreaMin = 5*5 if ptCCut and vtNCut then @@ -46,7 +46,7 @@ local function GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptC, vtN, nCopyPlane local TabellaTmSurfParallel = {} local i = nCopyPlane while i < nStep do - local SurfId = EgtSurfTmPlaneInBBox( nAddGrpId, ptC + ( i * dOffset) * vtN, vtN, b3BoxToDicing, GDB_RT.GLOB) + local SurfId = EgtSurfTmPlaneInBBox( nAddGrpId, ptC + ( i * dOffset) * vtN, vtN, b3BoxDicing, GDB_RT.GLOB) local nFacet = EgtSurfTmFacetCount( SurfId or GDB_ID.NULL) if nFacet == 0 then -- se sono al primo taglio do una possibilità in più di girare @@ -258,9 +258,9 @@ end -- VerifyFirstOrthoCut : -- CutTable: tabella dei tagli -- dOffsetParallel: offset della distanza dal punto centrale --- b3BoxToDicing: il grezzo della barra +-- b3BoxDicing: il grezzo della barra -- Verifica se l'asse X del box costruito sopra le 2 facce è più piccolo di un certo offset e quindi la faccia O è superflua -local function VerifyFirstOrthoCut( CutTable, dOffsetParallel, b3BoxToDicing, dNzLimDownUp) +local function VerifyFirstOrthoCut( CutTable, dOffsetParallel, b3BoxDicing, dNzLimDownUp) if not CutTable[1] or not CutTable[2] then return end @@ -275,7 +275,7 @@ local function VerifyFirstOrthoCut( CutTable, dOffsetParallel, b3BoxToDicing, dN -- normale alla faccia ortogonale local _, vtO = EgtSurfTmFacetCenter( CutOId, 0, GDB_ID.ROOT) vtO = vtO - vtO * vtN1 * vtN1 ; vtO:normalize() - local dMaxElev = EgtSurfTmFacetElevationInBBox( CutOId, 0, b3BoxToDicing, true, GDB_ID.ROOT) + local dMaxElev = EgtSurfTmFacetElevationInBBox( CutOId, 0, b3BoxDicing, true, GDB_ID.ROOT) -- calcolo lunghezza prima semi-faccia local asseX1 = vtO local asseY1 = vtN1 ^ asseX1 @@ -308,9 +308,9 @@ end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- ricavo i vertici del box -local function CalcolaPuntiEstremiBox( b3BoxToDicing) - local ptMin = b3BoxToDicing:getMin() - local ptMax = b3BoxToDicing:getMax() +local function CalcolaPuntiEstremiBox( b3BoxDicing) + local ptMin = b3BoxDicing:getMin() + local ptMax = b3BoxDicing:getMax() local TBoxPoint = {} table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMin:getY(), ptMin:getZ()), On = true}) table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMin:getY(), ptMin:getZ()), On = true}) @@ -337,7 +337,7 @@ end ---------------------------------------------------------------------------------------------------------------------------------------------------- -- ricavo l'altezza del BoundingBox assegnati gli estremi del grezzo e la feature -- le funzioni commentate permettono di vedere la creazione di BoundingBox -local function DistanzaMassima( nAddGrpId, ptC1, vtN1, ptC2, vtN2, b3BoxToDicing, TPoint) +local function DistanzaMassima( nAddGrpId, ptC1, vtN1, ptC2, vtN2, b3BoxDicing, TPoint) -- calcolo il riferimento nel piano 1 local Frame1 = Frame3d( ptC1, vtN1) -- determino l'ingombro in questo riferimento della parte di trave compresa nel o nei piani @@ -353,7 +353,7 @@ local function DistanzaMassima( nAddGrpId, ptC1, vtN1, ptC2, vtN2, b3BoxToDicing -- eventuale altra faccia if ptC2 and vtN2 then local IdAux = EgtGroup( nAddGrpId) - local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, b3BoxToDicing, GDB_RT.GLOB) + local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, b3BoxDicing, GDB_RT.GLOB) EgtCutSurfTmPlane( IdSurf2, ptC1, -vtN1, false, GDB_RT.GLOB) if IdSurf2 then local BB2 = EgtGetBBoxRef( IdSurf2, GDB_BB.STANDARD, Frame1) @@ -520,10 +520,6 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) if vtO:getZ() > 0.939 and abs( vtNInner:getY()) > 0.5 then vtO:rotate( vtNInner, 90) end - -- se taglio con testa da sotto - if OptionalParameters.bHeadFromBottom and vtO:getZ() > 0.05 then - vtO = -vtO - end -- calcolo le dimensioni dell'offset e dove posizionare la prima faccia: -- CopyPlane: 0 => crea la prima faccia direttamente sul punto passato -- CopyPlane: 1 => crea la prima faccia e tutte le altre con l'offset passato @@ -635,8 +631,8 @@ local function DiceCutTest() local nRawPart = EgtGetParent( nAddGrpId) local nBox = EgtGetFirstNameInGroup( nRawPart, 'Box') -- carico il bounding box della trave - -- local b3BoxToDicing = EgtGetBBoxGlob( nRawPart, GDB_BB.STANDARD ) - local b3BoxToDicing = EgtGetBBoxGlob( nBox, GDB_BB.STANDARD ) + -- local b3BoxDicing = EgtGetBBoxGlob( nRawPart, GDB_BB.STANDARD ) + local b3BoxDicing = EgtGetBBoxGlob( nBox, GDB_BB.STANDARD ) -- seleziono il Part e il Layer di destinazione EgtSetCurrPartLayer( nRawPart, nAddGrpId) @@ -655,9 +651,9 @@ local function DiceCutTest() local CutTable = {} if nFacet == 1 then - CutTable = DiceCut.GetDice( nAddGrpId, b3BoxToDicing, ptC1, vtN1, true) + CutTable = DiceCut.GetDice( nAddGrpId, b3BoxDicing, ptC1, vtN1, true) elseif nFacet == 2 then - CutTable = DiceCut.GetDice( nAddGrpId, b3BoxToDicing, ptC1, vtN1, false, TabPlanesFeatures[2].ptC, TabPlanesFeatures[2].vtN) + CutTable = DiceCut.GetDice( nAddGrpId, b3BoxDicing, ptC1, vtN1, false, TabPlanesFeatures[2].ptC, TabPlanesFeatures[2].vtN) end if EgtGetDebugLevel() >= 3 then From 1271205f2ca14585af1336f541146a0f86a67a80 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Fri, 31 Jan 2025 12:40:35 +0100 Subject: [PATCH 4/9] - in BLADETOWASTE primo implemento, non completo, del taglio singolo --- LuaLibs/BeamExec.lua | 39 ++--------------------- LuaLibs/DiceCut.lua | 2 +- Strategies/Standard/STR0005/STR0005.lua | 5 ++- StrategyLibs/BLADETOWASTE.lua | 42 +++++++++++++++++++++---- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index d8ef29a..7e47e07 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -1332,49 +1332,16 @@ function BeamExec.ProcessMachinings( PARTS) end EgtOutLog( ' *** AddMachinings ***', 1) - -- ordino le features + -- ordinamento di base delle feature vProc = OrderFeatures( vProc) -- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale MACHININGS = CalculateMachinings( vProc, PARTS[nPart]) + + -- ordinamento lavorazioni MACHININGS = MachiningLib.PrepareMachiningsForSorting( PARTS[nPart]) - - --TODO - rimuovere o mettere in Log, serve solo per test - -- TEST - local MachiningPropertiesBeforeSorting = {} - for i =1, #MACHININGS do - MachiningPropertiesBeforeSorting[i] = {} - MachiningPropertiesBeforeSorting[i] = { - ptCenter = MACHININGS[i].Machining.ptCenter, - nStage = MACHININGS[i].Machining.nStage, - nPartSegment = MACHININGS[i].Machining.nPartSegment, - sToolFamily = TOOLS[ MACHININGS[i].Machining.nToolIndex].sFamily, - dToolPerformanceIndex = TOOLS[ MACHININGS[i].Machining.nToolIndex].dPerformanceIndex, - sToolName = TOOLS[ MACHININGS[i].Machining.nToolIndex].sName, - vtToolDirection = MACHININGS[i].Machining.vtToolDirection - } - end - -- fine TEST - -- TODO completare ordinamento. Mancano le dipendenze. MACHININGS = BeamLib.StableSort( MACHININGS, MachiningLib.CompareMachinings) - - --TODO - rimuovere o mettere in Log, serve solo per test - -- TEST - local MachiningPropertiesAfterSorting = {} - for i =1, #MACHININGS do - MachiningPropertiesAfterSorting[i] = {} - MachiningPropertiesAfterSorting[i] = { - ptCenter = MACHININGS[i].Machining.ptCenter, - nStage = MACHININGS[i].Machining.nStage, - nPartSegment = MACHININGS[i].Machining.nPartSegment, - sToolFamily = TOOLS[ MACHININGS[i].Machining.nToolIndex].sFamily, - dToolPerformanceIndex = TOOLS[ MACHININGS[i].Machining.nToolIndex].dPerformanceIndex, - sToolName = TOOLS[ MACHININGS[i].Machining.nToolIndex].sName, - vtToolDirection = MACHININGS[i].Machining.vtToolDirection - } - end - -- fine TEST -- aggiungo la fase, se non è la prima if nOrd == 1 then diff --git a/LuaLibs/DiceCut.lua b/LuaLibs/DiceCut.lua index e8447cf..0ae2788 100644 --- a/LuaLibs/DiceCut.lua +++ b/LuaLibs/DiceCut.lua @@ -414,7 +414,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) bGetOrtoPlanes = true end - -- parametri opzionali + -- parametri opzionali e default -- box per dicing local b3BoxDicing = OptionalParameters.b3BoxDicing or Part.b3Part -- distanza tra piani paralleli diff --git a/Strategies/Standard/STR0005/STR0005.lua b/Strategies/Standard/STR0005/STR0005.lua index 34ceda8..297d262 100644 --- a/Strategies/Standard/STR0005/STR0005.lua +++ b/Strategies/Standard/STR0005/STR0005.lua @@ -201,7 +201,10 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) -- lavorazione a cubetti / taglio singolo if #Blade.Result == 0 and not bLeaveWasteAttached then - -- BladeToWaste + local bDropWholeWaste = Strategy.Parameters.sCuttingStrategy == 'DROP_WHOLE_WASTE' + local OptionalParameters = { bDropWholeWaste = bDropWholeWaste} + Blade.Result.Sorted = BladeToWaste.Make( Proc, Part, OptionalParameters) + end -- aggiunta lavorazioni diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index 5bb6f17..5b477d6 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -18,14 +18,43 @@ EgtOutLog( ' BLADETOWASTE started', 1) ------------------------------------------------------------------------------------------------------------- -function BLADETOWASTE.Make( ) - --- if dFeatureVolume < StrategyParameters.dMaxWasteVolume + 10 * GEO.EPS_SMALL --- and dFeatureMaxDimension < StrategyParameters.dMaxWasteLength + 10 * GEO.EPS_SMALL then - --- end +function BLADETOWASTE.Make( Proc, Part, OptionalParameters) + local Result = {} + -- parametri opzionali e default + local nToolIndex = OptionalParameters.nToolIndex + local bDropWholeWaste = OptionalParameters.bDropWholeWaste or false + local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part) + local dFeatureMaxDimension = max( Proc.b3Box:getDimX(), Proc.b3Box:getDimY()) + local bIsFeatureSmall = dFeatureVolume < StrategyParameters.dMaxWasteVolume + 10 * GEO.EPS_SMALL + and dFeatureMaxDimension < StrategyParameters.dMaxWasteLength + 10 * GEO.EPS_SMALL + + if Proc.nFct == 1 and ( bIsFeatureSmall or bDropWholeWaste) then + local EdgeToMachine = {} + -- ricerca utensile + if not nToolIndex then + local ToolSearchParameters = {} + for i = 1, #Proc.Faces[1].Edges do + if Proc.Faces[1].Edges[i].dElevation < EdgeToMachine.dElevation - 10 * GEO.EPS_SMALL then + EdgeToMachine = Proc.Faces[1].Edges[i] + end + end + ToolSearchParameters.dElevation = EdgeToMachine.dElevation + ToolSearchParameters.vtToolDirection = EdgeToMachine.vtN + ToolSearchParameters.bAllowTopHead = true + -- TODO bisognerà implementare anche la lama da sotto + ToolSearchParameters.bAllowBottomHead = false + ToolSearchParameters.bForceLongcutBlade = false + local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) + nToolIndex = ToolInfo.nToolIndex + end + + local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine) + table.insert( Result, Cutting) + + -- restituire tabella contenente lavorazioni, già con cloni se necessari + end @@ -50,6 +79,7 @@ function BLADETOWASTE.Make( ) + return Result end ------------------------------------------------------------------------------------------------------------- From 2f1b56ddc6d72dcf9dff155404d80b3cbe4ec0fd Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Fri, 31 Jan 2025 13:08:27 +0100 Subject: [PATCH 5/9] - in BLADETOWASTE taglio singolo funzionante, da completare --- LuaLibs/DiceCut.lua | 2 +- Strategies/Standard/STR0005/STR0005.lua | 11 +++++++---- StrategyLibs/BLADETOWASTE.lua | 11 +++++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/LuaLibs/DiceCut.lua b/LuaLibs/DiceCut.lua index 0ae2788..576de61 100644 --- a/LuaLibs/DiceCut.lua +++ b/LuaLibs/DiceCut.lua @@ -428,7 +428,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) -- distanza tra piani paralleli e piani di taglio (era sempre 0, serve???) local dTolerance = OptionalParameters.dTolerance or 0 -- inclinazione limite per taglio da sotto - local dNzLimDownUp = OptionalParameters.dNzLimDownUp BeamLib.GetNzLimDownUp( b3BoxDicing) + local dNzLimDownUp = OptionalParameters.dNzLimDownUp or BeamLib.GetNzLimDownUp( b3BoxDicing) --Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxDicing) diff --git a/Strategies/Standard/STR0005/STR0005.lua b/Strategies/Standard/STR0005/STR0005.lua index 297d262..e742d0f 100644 --- a/Strategies/Standard/STR0005/STR0005.lua +++ b/Strategies/Standard/STR0005/STR0005.lua @@ -116,6 +116,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) Blade.Result = {} local Cutting = {} local dMRRBlade = 0 + local dCompletionPercentage = 0 -- estensione oltre la coda local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0) @@ -194,7 +195,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) local dMRRBlade2 = MachiningLib.GetToolMRR( MRRParameters2) dMRRBlade = ( dMRRBlade1 + dMRRBlade2) / 2 - Cutting = Cutting2 + dCompletionPercentage = Cutting2.dCompletionPercentage -- se la lavorazione con codolo fallisce o non è possibile si proseguirà a quella con cubetti end @@ -202,9 +203,11 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) -- lavorazione a cubetti / taglio singolo if #Blade.Result == 0 and not bLeaveWasteAttached then local bDropWholeWaste = Strategy.Parameters.sCuttingStrategy == 'DROP_WHOLE_WASTE' - local OptionalParameters = { bDropWholeWaste = bDropWholeWaste} + local OptionalParameters = { bDropWholeWaste = bDropWholeWaste, dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume, dMaxWasteLength = Strategy.Parameters.dMaxWasteLength} Blade.Result.Sorted = BladeToWaste.Make( Proc, Part, OptionalParameters) + -- TODO la BladeToWaste dovrà restituire la dCompletionPercentage + dCompletionPercentage = Blade.Result.Sorted[#Blade.Result.Sorted].dCompletionPercentage end -- aggiunta lavorazioni @@ -225,12 +228,12 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) end -- TODO calcolo migliore area lavorata; se ho il codolo ha senso l'incompleta? se incompleta con codolo faccio i cubetti?? if nIsApplicableCount > 0 then - if Cutting.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then + if dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then Strategy.Result.sStatus = 'Completed' else Strategy.Result.sStatus = 'Not-Completed' -- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante - dFinalCompletionPercentage = Cutting.dCompletionPercentage + dFinalCompletionPercentage = dCompletionPercentage end else Strategy.Result.sStatus = 'Not-Applicable' diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index 5b477d6..c663360 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -24,11 +24,13 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) -- parametri opzionali e default local nToolIndex = OptionalParameters.nToolIndex local bDropWholeWaste = OptionalParameters.bDropWholeWaste or false + local dMaxWasteVolume = OptionalParameters.dMaxWasteVolume or 0 + local dMaxWasteLength = OptionalParameters.dMaxWasteLength or 0 local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part) local dFeatureMaxDimension = max( Proc.b3Box:getDimX(), Proc.b3Box:getDimY()) - local bIsFeatureSmall = dFeatureVolume < StrategyParameters.dMaxWasteVolume + 10 * GEO.EPS_SMALL - and dFeatureMaxDimension < StrategyParameters.dMaxWasteLength + 10 * GEO.EPS_SMALL + local bIsFeatureSmall = dFeatureVolume < dMaxWasteVolume + 10 * GEO.EPS_SMALL + and dFeatureMaxDimension < dMaxWasteLength + 10 * GEO.EPS_SMALL if Proc.nFct == 1 and ( bIsFeatureSmall or bDropWholeWaste) then local EdgeToMachine = {} @@ -36,7 +38,7 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) if not nToolIndex then local ToolSearchParameters = {} for i = 1, #Proc.Faces[1].Edges do - if Proc.Faces[1].Edges[i].dElevation < EdgeToMachine.dElevation - 10 * GEO.EPS_SMALL then + if ( i == 1) or Proc.Faces[1].Edges[i].dElevation < EdgeToMachine.dElevation - 10 * GEO.EPS_SMALL then EdgeToMachine = Proc.Faces[1].Edges[i] end end @@ -50,7 +52,8 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) nToolIndex = ToolInfo.nToolIndex end - local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine) + local OptionalParametersFaceByBlade = { dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA} + local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParametersFaceByBlade) table.insert( Result, Cutting) -- restituire tabella contenente lavorazioni, già con cloni se necessari From 7eb83ccf7970982fa0c804a16aaba52bb7d5a7c0 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Fri, 31 Jan 2025 17:23:11 +0100 Subject: [PATCH 6/9] - in MachiningLib migliorie a FindBlade - migliorata BLADETOWASTE - in FACEBYBLADE la residualDepth si esprime rispetto alla DephToMachine passata e non rispetto all'elevazione del lato --- LuaLibs/MachiningLib.lua | 26 +++++++++++++++++++++-- Strategies/Standard/STR0005/STR0005.lua | 6 +----- StrategyLibs/BLADETOWASTE.lua | 28 ++++++++++++++++++------- StrategyLibs/FACEBYBLADE.lua | 4 ++-- 4 files changed, 47 insertions(+), 17 deletions(-) diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index 5b9d0fb..915fb3b 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -319,6 +319,7 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) ToolSearchParameters.bForceLongcutBlade = ToolSearchParameters.bForceLongcutBlade or false local nBestToolIndex + local dBestToolResidualDepth = 0 for i = 1, #TOOLS do local bIsToolCompatible = false @@ -333,19 +334,40 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) end if bIsToolCompatible then - if not nBestToolIndex 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 diff --git a/Strategies/Standard/STR0005/STR0005.lua b/Strategies/Standard/STR0005/STR0005.lua index e742d0f..2afbc58 100644 --- a/Strategies/Standard/STR0005/STR0005.lua +++ b/Strategies/Standard/STR0005/STR0005.lua @@ -114,7 +114,6 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) Strategy.Result = {} Strategy.Result.sInfo = '' Blade.Result = {} - local Cutting = {} local dMRRBlade = 0 local dCompletionPercentage = 0 @@ -204,10 +203,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) if #Blade.Result == 0 and not bLeaveWasteAttached then local bDropWholeWaste = Strategy.Parameters.sCuttingStrategy == 'DROP_WHOLE_WASTE' local OptionalParameters = { bDropWholeWaste = bDropWholeWaste, dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume, dMaxWasteLength = Strategy.Parameters.dMaxWasteLength} - Blade.Result.Sorted = BladeToWaste.Make( Proc, Part, OptionalParameters) - - -- TODO la BladeToWaste dovrà restituire la dCompletionPercentage - dCompletionPercentage = Blade.Result.Sorted[#Blade.Result.Sorted].dCompletionPercentage + Blade.Result.Sorted, dCompletionPercentage = BladeToWaste.Make( Proc, Part, OptionalParameters) end -- aggiunta lavorazioni diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index c663360..95f6886 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -20,6 +20,7 @@ EgtOutLog( ' BLADETOWASTE started', 1) function BLADETOWASTE.Make( Proc, Part, OptionalParameters) local Result = {} + local dCompletionPercentage = 0 -- parametri opzionali e default local nToolIndex = OptionalParameters.nToolIndex @@ -27,13 +28,18 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) local dMaxWasteVolume = OptionalParameters.dMaxWasteVolume or 0 local dMaxWasteLength = OptionalParameters.dMaxWasteLength or 0 + -- dimensioni feature local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part) local dFeatureMaxDimension = max( Proc.b3Box:getDimX(), Proc.b3Box:getDimY()) local bIsFeatureSmall = dFeatureVolume < dMaxWasteVolume + 10 * GEO.EPS_SMALL and dFeatureMaxDimension < dMaxWasteLength + 10 * GEO.EPS_SMALL + -- si taglia tutto lo scarto in una sola lavorazione if Proc.nFct == 1 and ( bIsFeatureSmall or bDropWholeWaste) then + local Cutting = {} local EdgeToMachine = {} + local dDepthToMachine = 0 + local ToolInfo = {} -- ricerca utensile if not nToolIndex then local ToolSearchParameters = {} @@ -42,21 +48,27 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) EdgeToMachine = Proc.Faces[1].Edges[i] end end - ToolSearchParameters.dElevation = EdgeToMachine.dElevation + dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA + ToolSearchParameters.dElevation = dDepthToMachine ToolSearchParameters.vtToolDirection = EdgeToMachine.vtN ToolSearchParameters.bAllowTopHead = true -- TODO bisognerà implementare anche la lama da sotto ToolSearchParameters.bAllowBottomHead = false ToolSearchParameters.bForceLongcutBlade = false - local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) + ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) nToolIndex = ToolInfo.nToolIndex end - local OptionalParametersFaceByBlade = { dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA} - local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParametersFaceByBlade) - table.insert( Result, Cutting) + if ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then + local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, nToolIndex = nToolIndex} + Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParametersFaceByBlade) + end + if Cutting.bIsApplicable or bDropWholeWaste then + table.insert( Result, Cutting) + dCompletionPercentage = Cutting.dCompletionPercentage or dCompletionPercentage + end - -- restituire tabella contenente lavorazioni, già con cloni se necessari + return Result, dCompletionPercentage end @@ -81,8 +93,8 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) - - return Result + -- restituire tabella contenente lavorazioni, già con cloni se necessari + return Result, dCompletionPercentage end ------------------------------------------------------------------------------------------------------------- diff --git a/StrategyLibs/FACEBYBLADE.lua b/StrategyLibs/FACEBYBLADE.lua index 5ed89eb..b0fdcd1 100644 --- a/StrategyLibs/FACEBYBLADE.lua +++ b/StrategyLibs/FACEBYBLADE.lua @@ -102,7 +102,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar local bForceLongcutBlade = OptionalParameters.bForceLongcutBlade or false local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000 local dPocketHeight = OptionalParameters.dPocketHeight or 0 - local dDepthToMachine = min( OptionalParameters.dDepthToMachine or EdgeToMachine.dElevation, EdgeToMachine.dElevation) + local dDepthToMachine = OptionalParameters.dDepthToMachine or EdgeToMachine.dElevation local bIsSplitFeature = OptionalParameters.bIsSplitFeature or false local bOppositeToolDirection = OptionalParameters.bOppositeToolDirection or false local sDepth = OptionalParameters.sDepth or 0 @@ -204,7 +204,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar end else Cutting.dDepthToMachine = TOOLS[Cutting.nToolIndex].dMaxDepth - 1 - Cutting.dResidualDepth = EdgeToMachine.dElevation - Cutting.dDepthToMachine + Cutting.dResidualDepth = dDepthToMachine - Cutting.dDepthToMachine if bOppositeToolDirection then Cutting.dRadialOffset = -Cutting.dDepthToMachine else From 81c0acbde17d704b16142528193b5b730933ddb2 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Fri, 31 Jan 2025 18:06:00 +0100 Subject: [PATCH 7/9] =?UTF-8?q?-=20in=20FACEBYBLADE=20di=20default=20si=20?= =?UTF-8?q?inverte=20l'utensile=20per=20rispettare=20la=20concordanza=20(T?= =?UTF-8?q?oolInvert)=20solo=20se=20=C3=A8=20vero=20il=20parametro=20opzio?= =?UTF-8?q?nale=20bAllowToolInvert=20-=20parametro=20opzionale=20passato?= =?UTF-8?q?=20in=20STR0003=20->=20Blade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Strategies/Standard/STR0003/STR0003.lua | 2 +- StrategyLibs/FACEBYBLADE.lua | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Strategies/Standard/STR0003/STR0003.lua b/Strategies/Standard/STR0003/STR0003.lua index 1265c62..384d5f5 100644 --- a/Strategies/Standard/STR0003/STR0003.lua +++ b/Strategies/Standard/STR0003/STR0003.lua @@ -294,7 +294,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters) -- lama - calcolo lavorazioni local Cutting = {} - local OptionalParameters = { bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature} + local OptionalParameters = { bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature, bAllowToolInvert = true} if Proc.Topology.sFamily == 'Tunnel' then OptionalParameters.bOppositeToolDirection = true Cutting = FaceByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters) diff --git a/StrategyLibs/FACEBYBLADE.lua b/StrategyLibs/FACEBYBLADE.lua index b0fdcd1..f5085a5 100644 --- a/StrategyLibs/FACEBYBLADE.lua +++ b/StrategyLibs/FACEBYBLADE.lua @@ -111,6 +111,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar if OptionalParameters.dPocketHeight then dLongitudinalOffset = 0 end + local bAllowToolInvert = OptionalParameters.bAllowToolInvert or false local sUserNotes = OptionalParameters.sUserNotes or '' -- lunghezze e punti caratteristici della lavorazione e del lato lavorato @@ -186,7 +187,8 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar Cutting.bInvert = not Cutting.bInvert end -- TODO gestire lama da sotto e lama downUp - if FaceToMachine.vtN:getZ() < - 10 * GEO.EPS_SMALL then + -- TODO qui il check della vtN dovrebbe essere sulla dMaxNegativeAngle in SetupInfo dell'utensile? + if bAllowToolInvert and FaceToMachine.vtN:getZ() < - 10 * GEO.EPS_SMALL then Cutting.bToolInvert = true Cutting.bInvert = not Cutting.bInvert else From b229b21e6457465509f0825f79c13a3abf6a631a Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Mon, 24 Feb 2025 17:41:39 +0100 Subject: [PATCH 8/9] - in BLADETOWASTE primo implemento di lavorazione a cubetti, non funzionante --- LuaLibs/MachiningLib.lua | 1 + Strategies/Standard/STR0005/STR0005.lua | 6 ++--- StrategyLibs/BLADETOWASTE.lua | 31 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index 915fb3b..d5564ea 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -297,6 +297,7 @@ 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) +-- TODO bisogna leggere vtToolDirection in arrivo e confrontarlo con il SetupInfo function MachiningLib.FindBlade( Proc, ToolSearchParameters) local ToolInfo = {} diff --git a/Strategies/Standard/STR0005/STR0005.lua b/Strategies/Standard/STR0005/STR0005.lua index 2afbc58..7662d10 100644 --- a/Strategies/Standard/STR0005/STR0005.lua +++ b/Strategies/Standard/STR0005/STR0005.lua @@ -123,7 +123,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) dExtendAfterTail = 10000 end - -- considerazione necessarie a determinare se lasciare il legno attaccato oppure no + -- considerazioni necessarie a determinare se lavorare con codolo oppure no local dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( Proc, Part) local bLeaveWasteAttached = Strategy.Parameters.sCuttingStrategy == 'LEAVE_WASTE_ATTACHED' local bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN}) @@ -195,8 +195,6 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) dMRRBlade = ( dMRRBlade1 + dMRRBlade2) / 2 dCompletionPercentage = Cutting2.dCompletionPercentage - - -- se la lavorazione con codolo fallisce o non è possibile si proseguirà a quella con cubetti end -- lavorazione a cubetti / taglio singolo @@ -222,7 +220,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters) Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Sorted[i].sMessage end end - -- TODO calcolo migliore area lavorata; se ho il codolo ha senso l'incompleta? se incompleta con codolo faccio i cubetti?? + -- TODO migliorare calcolo area lavorata; se ho il codolo ha senso l'incompleta? se incompleta con codolo faccio i cubetti?? if nIsApplicableCount > 0 then if dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then Strategy.Result.sStatus = 'Completed' diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index 95f6886..4eb3edb 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -9,8 +9,10 @@ require( 'EgtBase') -- Carico i dati globali local BeamData = require( 'BeamData') +local BeamLib = require( 'BeamLib') local FeatureLib = require( 'FeatureLib') local MachiningLib = require( 'MachiningLib') +local DiceCut = require( 'DiceCut') -- strategie di base local FaceByBlade = require('FACEBYBLADE') @@ -22,6 +24,15 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) local Result = {} local dCompletionPercentage = 0 + -- controlli preventivi + if Proc.nFct > 2 then + error( 'BladeToWaste : max 2 faces supported') + elseif Proc.nFct == 2 then + if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][2] < -91 then + error( 'BladeToWaste : angle between faces must be concave and >= 90deg') + end + end + -- parametri opzionali e default local nToolIndex = OptionalParameters.nToolIndex local bDropWholeWaste = OptionalParameters.bDropWholeWaste or false @@ -71,6 +82,26 @@ function BLADETOWASTE.Make( Proc, Part, OptionalParameters) return Result, dCompletionPercentage end + -- lavorazione con cubetti + -- se due facce, la faccia principale è la più grande + local Face1 = Proc.Faces[1] + local Face2 = {} + if Proc.nFct == 2 then + Face2 = Proc.Faces[2] + end + -- direzione migliore di lavoro, per la ricerca utensile + local _, dCutH, dCutV = BeamLib.GetFaceHvRefDim( Proc.Id, 0, Part.b3Raw) + -- ricerca utensile + local ToolSearchParameters = {} + ToolSearchParameters.vtToolDirection = EdgeToMachine.vtN + ToolSearchParameters.bAllowTopHead = true + -- TODO bisognerà implementare anche la lama da sotto + ToolSearchParameters.bAllowBottomHead = false + ToolSearchParameters.bForceLongcutBlade = false + ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters) + nToolIndex = ToolInfo.nToolIndex + + local vCuts = DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) From 20c10f495d22b940c2a317cefb846382455eb9c5 Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Tue, 25 Feb 2025 18:30:20 +0100 Subject: [PATCH 9/9] - aggiornati riferimenti a GetSetupInfo con nuovi nomi --- LuaLibs/MachiningLib.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index d5564ea..79befe3 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -216,9 +216,9 @@ function MachiningLib.FindMill( Proc, ToolSearchParameters) -- 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 + elseif TOOLS[i].SetupInfo.HeadType.bTop 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 + elseif TOOLS[i].SetupInfo.HeadType.bBottom 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 @@ -326,9 +326,9 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) if TOOLS[i].sFamily == 'SAWBLADE' then if ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then - bIsToolCompatible = TOOLS[i].SetupInfo.bIsTopHead + bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bTop elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then - bIsToolCompatible = TOOLS[i].SetupInfo.bIsBottomHead + bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bBottom else bIsToolCompatible = true end @@ -409,9 +409,9 @@ function MachiningLib.FindChainSaw( Proc, ToolSearchParameters) if TOOLS[i].sFamily == 'MORTISE' then if ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then - bIsToolCompatible = TOOLS[i].SetupInfo.bIsTopHead + bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bTop elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then - bIsToolCompatible = TOOLS[i].SetupInfo.bIsBottomHead + bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bBottom else bIsToolCompatible = true end