diff --git a/BatchProcessNew.lua b/BatchProcessNew.lua index 06de795..aafea38 100644 --- a/BatchProcessNew.lua +++ b/BatchProcessNew.lua @@ -566,7 +566,11 @@ if bToProcess then for i = 1, #RESULT do local sMsg = '' if RESULT[i].sType == 'Feature' then - sMsg = RESULT[i].ChosenStrategy.sInfo + if RESULT[i].ChosenStrategy.bIsApplyOk then + sMsg = RESULT[i].ChosenStrategy.sInfo + else + sMsg = RESULT[i].ChosenStrategy.sApplyInfo + end elseif RESULT[i].sType == 'Part' then sMsg = RESULT[i].sMsg end diff --git a/LuaLibs/BasicCustomerStrategies.lua b/LuaLibs/BasicCustomerStrategies.lua index 5b4775a..1c91db6 100644 --- a/LuaLibs/BasicCustomerStrategies.lua +++ b/LuaLibs/BasicCustomerStrategies.lua @@ -61,6 +61,7 @@ local function GetStrategies_Egalware( Proc) --------------------------------------------------------------------- -- Feature : Double Cut (1-11) elseif ID.IsDoubleCut( Proc) then + Strategies = { { sStrategyId = 'STR0005'}} --------------------------------------------------------------------- -- Feature : Ridge or Valley Cut (0-12) elseif ID.IsDoubleLongitudinalCut( Proc) then @@ -361,6 +362,7 @@ local function GetStrategies_Essetre( Proc) --------------------------------------------------------------------- -- Feature : Double Cut (1-11) elseif ID.IsDoubleCut( Proc) then + Strategies = { { sStrategyId = 'STR0005'}} --------------------------------------------------------------------- -- Feature : Ridge or Valley Cut (0-12) elseif ID.IsDoubleLongitudinalCut( Proc) then diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 1a53cef..2acb6e7 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -1036,7 +1036,6 @@ local function OrderFeatures( vProc) end ------------------------------------------------------------------------------------------------------------- --- TODO gestire Proc che non hanno una ChosenStrategy, perchè sono specchiate, multi (si legge il risultato da un'altra feature?) o non è stata trovata una strategia local function AddFeatureResultToGlobalList( Proc, OptionalParameters) local sStrategyId local sStatus @@ -1085,6 +1084,9 @@ local function AddFeatureResultToGlobalList( Proc, OptionalParameters) RESULT[#RESULT].AvailableStrategies = BeamLib.TableCopyDeep( Proc.AvailableStrategies) end + -- si segna nella Proc la sua posizione nel RESULT + Proc.nIndexInResult = #RESULT + return RESULT end @@ -1587,6 +1589,17 @@ function BeamExec.ProcessMachinings( PARTS) bIsCombinationMachinable = bIsCombinationMachinable and bAllStrategiesApplied end + -- cancellazione entità create ma non usate + -- TODO funzione? + local idAddGroup = BeamLib.GetAddGroup( PARTS[nPart].id) + local idCreatedEntity = EgtGetFirstInGroup( idAddGroup or GDB_ID.NULL) + while idCreatedEntity do + if EgtGetLevel( idCreatedEntity) == GDB_LV.TEMP then + EgtErase( idCreatedEntity) + end + idCreatedEntity = EgtGetNext( idCreatedEntity) + end + -- ordinamento lavorazioni -- TODO completare ordinamento. Mancano le dipendenze. -- TODO la FinalizeSorting andrebbe rimossa e usato un sorting che non viola le dipendenze diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index ce9a446..9531b97 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -870,7 +870,13 @@ function MachiningLib.AddOperations( vProc, Part, sRotation) bAreAllMachiningApplyOk = false nErr, sErr = EgtGetLastMachMgrError() EgtSetOperationMode( nOperationId, false) + -- update risultati + -- TODO è corretto mettere non applicabile????? + RESULT[MACHININGS[i].Proc.nIndexInResult].ChosenStrategy.sStatus = 'Not-Applicable' + RESULT[MACHININGS[i].Proc.nIndexInResult].ChosenStrategy.sApplyInfo = sErr + RESULT[MACHININGS[i].Proc.nIndexInResult].ChosenStrategy.nApplyError = nErr end + RESULT[MACHININGS[i].Proc.nIndexInResult].ChosenStrategy.bIsApplyOk = bIsApplyOk -- 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 diff --git a/Strategies/AvailableStrategyList.json b/Strategies/AvailableStrategyList.json index 2cee64b..36b2ba8 100644 --- a/Strategies/AvailableStrategyList.json +++ b/Strategies/AvailableStrategyList.json @@ -26,7 +26,7 @@ "nGrp": "1", "TopologyList" : [ { "sName": "Feature", - "StrategyList" : [ ] + "StrategyList" : [ { "sStrategyID": "STR0005" } ] } ] }, diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index 0029878..2aaf0ec 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -18,7 +18,6 @@ local DiceCut = require( 'DiceCut') local FaceByBlade = require('FACEBYBLADE') -- tabella per definizione modulo -local Machinings = {} local FeatureInfo = {} ------------------------------------------------------------------------------------------------------------- @@ -135,7 +134,10 @@ local function GetBestBlade( Proc, Part, Face, OptionalParameters) local nChosenToolIndex local sChosenBladeType - -- parametri opzionali + -- parametri opzionali e default + if not OptionalParameters then + OptionalParameters = {} + end local dMinNzTopBladeIfEqual = OptionalParameters.dMinNzTopBlade or sin(-5) local dMaxNyTopBlade = OptionalParameters.dMaxNyTopBlade or sin(1) local dShortPartLength = OptionalParameters.dShortPartLength or BeamData.LEN_SHORT_PART @@ -235,21 +237,28 @@ end local function CutWholeWaste( Proc, Part, OptionalParameters) + local Machinings = {} local Cutting = {} local Result = {} local EdgeToMachine = {} - local nToolIndex local sChosenBladeType = '' local dDepthToMachine = 0 local dCompletionPercentage = 0 + -- parametri opzionali e default + if not OptionalParameters then + OptionalParameters = {} + end + local nToolIndex = OptionalParameters.nToolIndex + local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000 + -- lato da lavorare in base al tipo di lama local EdgeToMachineTopBlade = GetEdgeToMachine( Proc.Faces[1].Edges, Proc.Faces[1].vtN, 'Top') local EdgeToMachineBottomBlade = GetEdgeToMachine( Proc.Faces[1].Edges, Proc.Faces[1].vtN, 'Bottom') local EdgeToMachineTopBladeDownUp = GetEdgeToMachine( Proc.Faces[1].Edges, Proc.Faces[1].vtN, 'TopDownUp') -- scelta lama da sopra o da sotto - if OptionalParameters.nToolIndex then + if nToolIndex then nToolIndex = OptionalParameters.nToolIndex else local OptionalParametersGetBestBlade = { dElevationTop = EdgeToMachineTopBlade.dElevation + BeamData.CUT_EXTRA, @@ -262,7 +271,6 @@ local function CutWholeWaste( Proc, Part, OptionalParameters) -- utensile non trovato if not nToolIndex then Result = FeatureLib.GetStrategyResultNotApplicable( 'Blade not found') - return Machinings, Result end @@ -280,7 +288,8 @@ local function CutWholeWaste( Proc, Part, OptionalParameters) -- TODO qui gestire il caso in cui si può tagliare da due lati (inizialmente solo se vtN:Y è ~= 0?). Andranno ricercati gli utensili di nuovo con l'elevazione a metà?? if dResidualDepth < 10 * GEO.EPS_SMALL then - local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, nToolIndex = nToolIndex, dExtendAfterTail = OptionalParameters.dExtendAfterTail} + local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, nToolIndex = nToolIndex, dExtendAfterTail = dExtendAfterTail} + Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParametersFaceByBlade) end if Cutting.bIsApplicable then @@ -309,59 +318,22 @@ local function CutWholeWaste( Proc, Part, OptionalParameters) end -function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) - Machinings = {} +local function CutWithDicing( Proc, Part, OptionalParameters) + local Machinings = {} local Result = {} - -- disambiguazione feature vs id trimesh - local Proc = {} - if type( ProcOrId) == "table" then - Proc = ProcOrId - elseif type( ProcOrId) == "number" then - Proc = FeatureLib.GetProcFromTrimesh( ProcOrId, Part) - else - error( 'BLADETOWASTE : Only feature or trimesh supported') - end - - -- 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 if not OptionalParameters then OptionalParameters = {} end local nToolIndex = OptionalParameters.nToolIndex - local dMaxWasteVolume = OptionalParameters.dMaxWasteVolume or 0 - local dMaxWasteLength = OptionalParameters.dMaxWasteLength or 0 local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000 + local b3BoxDicing = OptionalParameters.b3BoxDicing local bSaveAddedGeometries = OptionalParameters.bSaveAddedGeometries if bSaveAddedGeometries == nil then bSaveAddedGeometries = true end - -- dimensioni feature - FeatureInfo.dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part) - FeatureInfo.dFeatureMaxDimension = max( Proc.b3Box:getDimX(), Proc.b3Box:getDimY()) - FeatureInfo.bIsFeatureSmall = FeatureInfo.dFeatureVolume < dMaxWasteVolume + 10 * GEO.EPS_SMALL - and FeatureInfo.dFeatureMaxDimension < dMaxWasteLength + 10 * GEO.EPS_SMALL - - -- si taglia tutto lo scarto in una sola lavorazione - -- TODO qui si deve entrare anche se lo spessore lama è maggiore dell'elevazione delle faccia - if Proc.nFct == 1 and FeatureInfo.bIsFeatureSmall then - Machinings, Result = CutWholeWaste( Proc, Part, OptionalParameters) - if Result.sStatus == 'Completed' then - return Machinings, Result - end - end - - -- TODO la lavorazione con cubetti va messa in una funzione - -- lavorazione con cubetti -- scelta faccia da lavorare -- se due facce, la faccia principale Face1 è la più grande local Face1 = Proc.Faces[1] @@ -376,11 +348,13 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) -- scelta lama da sopra o da sotto local sChosenBladeType = '' if not nToolIndex then - nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part, Face1, OptionalParameters) + nToolIndex, sChosenBladeType = GetBestBlade( Proc, Part, Face1) end -- se non trovata lama la lavorazione non è fattibile if not nToolIndex then + Result = FeatureLib.GetStrategyResultNotApplicable( 'Blade not found') + return Machinings, Result end @@ -400,6 +374,7 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) OptionalParametersDiceCut.dOffsetOrthogonal = dDiceDimension OptionalParametersDiceCut.dOffsetOrthogonalReduced = dDiceDimensionReduced OptionalParametersDiceCut.dMinNzDownUp = dMinNzDownUp + OptionalParametersDiceCut.b3BoxDicing = b3BoxDicing local vCuts = DiceCut.GetDice( Part, Face1, Face2, OptionalParametersDiceCut) -- se nessun cubetto trovato, si richiama il taglio singolo @@ -415,7 +390,7 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) local bAreOrthogonalCutsInverted = false for i = 1, #vCuts do for j = 1, #vCuts[i] do - SetDiceFaceInfo( Proc, vCuts[i][j]) + SetDiceFaceInfo( Proc, vCuts[i][j], bSaveAddedGeometries) if ( i % 2) == 1 then local vtO = EgtSurfTmFacetNormVersor( vCuts[i][j], 0, GDB_ID.ROOT) if ( Face1.vtN:getY() > 0.766 and vtO:getY() < -0.05) or @@ -560,6 +535,145 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) return Machinings, Result end + +local function MakeOneFace( ProcOrId, Part, OptionalParameters) + local Machinings = {} + local Result = {} + + -- disambiguazione feature vs id trimesh + local Proc = {} + if type( ProcOrId) == "table" then + Proc = ProcOrId + elseif type( ProcOrId) == "number" then + Proc = FeatureLib.GetProcFromTrimesh( ProcOrId, Part) + else + error( 'BLADETOWASTE : Only feature or trimesh supported') + end + + -- parametri opzionali e default + if not OptionalParameters then + OptionalParameters = {} + end + local bForceDicing = OptionalParameters.bForceDicing or false + + -- si taglia tutto lo scarto in una sola lavorazione + -- TODO qui si deve entrare anche se lo spessore lama è maggiore dell'elevazione delle faccia + if FeatureInfo.bIsFeatureSmall and not bForceDicing then + Machinings, Result = CutWholeWaste( Proc, Part, OptionalParameters) + end + + -- se non completata con taglio singolo, lavorazione con cubetti + if not Result.sStatus or Result.sStatus ~= 'Completed' then + Machinings, Result = CutWithDicing( Proc, Part, OptionalParameters) + end + + return Machinings, Result +end + + +function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) + local Machinings = {} + local Result = {} + + -- disambiguazione feature vs id trimesh + local Proc = {} + if type( ProcOrId) == "table" then + Proc = ProcOrId + elseif type( ProcOrId) == "number" then + Proc = FeatureLib.GetProcFromTrimesh( ProcOrId, Part) + else + error( 'BLADETOWASTE : Only feature or trimesh supported') + end + + -- controlli preventivi + if Proc.nFct > 2 then + error( 'BladeToWaste : max 2 faces supported') + end + + -- parametri opzionali e default + -- quelli non censiti sono gestiti direttamente nelle funzioni sotto e devono quindi solo transitare + if not OptionalParameters then + OptionalParameters = {} + end + local dMaxWasteVolume = OptionalParameters.dMaxWasteVolume or 0 + local dMaxWasteLength = OptionalParameters.dMaxWasteLength or 0 + local bSaveAddedGeometries = OptionalParameters.bSaveAddedGeometries + if bSaveAddedGeometries == nil then + bSaveAddedGeometries = true + end + + -- dimensioni feature + FeatureInfo.dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part) + FeatureInfo.dFeatureMaxDimension = max( Proc.b3Box:getDimX(), Proc.b3Box:getDimY()) + FeatureInfo.bIsFeatureSmall = FeatureInfo.dFeatureVolume < dMaxWasteVolume + 10 * GEO.EPS_SMALL + and FeatureInfo.dFeatureMaxDimension < dMaxWasteLength + 10 * GEO.EPS_SMALL + + -- calcolo lavorazioni + if Proc.nFct == 1 then + Machinings, Result = MakeOneFace( Proc, Part, OptionalParameters) + + elseif Proc.nFct == 2 then + local dAngleBetweenFaces = Proc.AdjacencyMatrix[1][2] + + -- feature convessa: lavorata come 2 facce singole con prolungamento + if dAngleBetweenFaces > 10 * GEO.EPS_SMALL then + -- si creano superfici singole per le facce, estese fino al box della parte + local nAddGrpId = BeamLib.GetAddGroup( Part.id) + local idFace1 = EgtSurfTmPlaneInBBox( nAddGrpId, Proc.Faces[1].ptCenter, Proc.Faces[1].vtN, Part.b3Part, GDB_ID.ROOT) + local idFace2 = EgtSurfTmPlaneInBBox( nAddGrpId, Proc.Faces[2].ptCenter, Proc.Faces[2].vtN, Part.b3Part, GDB_ID.ROOT) + if not bSaveAddedGeometries then + EgtSetLevel( idFace1, GDB_LV.TEMP) + EgtSetLevel( idFace2, GDB_LV.TEMP) + end + + -- lavorazione facce + local Machinings1, Result1 = MakeOneFace( idFace1, Part, OptionalParameters) + local Machinings2, Result2 = MakeOneFace( idFace2, Part, OptionalParameters) + + -- tutte le lavorazioni raggruppatee e calcolo area lavorata + local dAreaToMachineTotal = 0 + for i = 1, #Machinings1 do + if Machinings1[i].bIsApplicable then + table.insert( Machinings, Machinings1[i]) + dAreaToMachineTotal = dAreaToMachineTotal + Machinings1[i].dAreaToMachine + end + end + for i = 1, #Machinings2 do + if Machinings2[i].bIsApplicable then + table.insert( Machinings, Machinings2[i]) + dAreaToMachineTotal = dAreaToMachineTotal + Machinings2[i].dAreaToMachine + end + end + + -- calcolo risultati + Result.nQuality = FeatureLib.GetStrategyQuality( Machinings) + Result.dCompletionPercentage = dAreaToMachineTotal / ( Proc.Faces[1].dArea + Proc.Faces[2].dArea) * 100 + Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Result.dCompletionPercentage) + Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Machinings) + Result.dMRR = ( FeatureInfo.dFeatureVolume / Result.dTimeToMachine) / pow( 10, 6) + if Result1.sStatus == 'Completed' and Result2.sStatus == 'Completed' then + Result.sStatus = 'Completed' + elseif Result1.sStatus == 'Completed' or Result2.sStatus == 'Completed' then + Result.sStatus = 'Not-Completed' + else + Result.sStatus = 'Not-Applicable' + Result = FeatureLib.GetStrategyResultNotApplicable() + end + + -- feature concava >= 90deg: lavorata con cubetti + elseif dAngleBetweenFaces >= -91 then + Machinings, Result = CutWithDicing( Proc, Part, OptionalParameters) + + -- feature concava < 90deg: lavorata come 2 facce singole con accorciamento + else + -- TODO da fare + end + + end + + return Machinings, Result +end + ------------------------------------------------------------------------------------------------------------- return BLADETOWASTE \ No newline at end of file diff --git a/StrategyLibs/FACEBYBLADE.lua b/StrategyLibs/FACEBYBLADE.lua index 0a6b4c2..d4e7f99 100644 --- a/StrategyLibs/FACEBYBLADE.lua +++ b/StrategyLibs/FACEBYBLADE.lua @@ -26,8 +26,8 @@ local function GetLeadInOutType( Machining) else sLeadInOutType = 'Tangent' end - elseif abs( Machining.vtEdgeDirection:getZ()) < 0.7 then - sLeadInOutType = 'Tangent' + elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then + sLeadInOutType = 'Perpendicular' else -- TODO qui attacco tangenziale speciale tutto da un lato sLeadInOutType = 'Tangent' @@ -42,7 +42,7 @@ local function GetLeadInOutType( Machining) sLeadInOutType = 'Tangent' end elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then - sLeadInOutType = 'Tangent' + sLeadInOutType = 'Perpendicular' else -- TODO qui attacco tangenziale speciale tutto da un lato sLeadInOutType = 'Tangent' @@ -96,8 +96,13 @@ local function CalculateLeadInOut( Machining, EdgeToMachine, Part) LeadIn.dPerpDistance = 1 LeadOut.dPerpDistance = 1 else - LeadIn.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 - LeadOut.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + if abs( Machining.vtEdgeDirection:getZ()) > 0.707 then + LeadIn.dPerpDistance = 1 + LeadOut.dPerpDistance = 1 + else + LeadIn.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + LeadOut.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + end end end LeadIn.dElevation = 0