From 74a12a4a42f8531a85da907033eb7c0a4a158d5c Mon Sep 17 00:00:00 2001 From: "luca.mazzoleni" Date: Tue, 25 Nov 2025 15:19:09 +0100 Subject: [PATCH] =?UTF-8?q?-=20funzioni=20di=20precollisione=20lama=20spos?= =?UTF-8?q?tate=20in=20libreria=20apposita=20PreCollisionLib=20-=20calcolo?= =?UTF-8?q?=20tempo=20esecuzione=20migliorato=20(TimeLib=20e=20riferimenti?= =?UTF-8?q?)=20-=20idTempGroup=20ora=20=C3=A8=20scritto=20nel=20Part=20per?= =?UTF-8?q?=20evitare=20di=20ricercarlo=20ogni=20volta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BatchProcessNew.lua | 21 ++- LuaLibs/BeamExec.lua | 4 + LuaLibs/DiceCut.lua | 2 +- LuaLibs/FeatureLib.lua | 2 +- LuaLibs/MachiningLib.lua | 228 ++---------------------- LuaLibs/PreCollisionLib.lua | 225 +++++++++++++++++++++++ LuaLibs/TimeLib.lua | 132 +++++++++----- Process.lua | 18 +- Strategies/Standard/STR0002/STR0002.lua | 2 +- Strategies/Standard/STR0015/STR0015.lua | 2 +- StrategyLibs/BLADETOWASTE.lua | 7 +- StrategyLibs/FACEBYBLADE.lua | 12 +- 12 files changed, 368 insertions(+), 287 deletions(-) create mode 100644 LuaLibs/PreCollisionLib.lua diff --git a/BatchProcessNew.lua b/BatchProcessNew.lua index fc6df01..dce4acf 100644 --- a/BatchProcessNew.lua +++ b/BatchProcessNew.lua @@ -182,10 +182,8 @@ end ------------------------------------------------------------------------------------------------------------- -- calcolo tempo esecuzione -if EgtGetDebugLevel() >= 3 then - TIMER:start() - EgtOutLog( ' Execution timer started') -end +TIMER:start() +EgtOutLog( ' Execution timer started') -- script principale @@ -436,6 +434,9 @@ if bToProcess then -- recupero parametri generali da progetto BeamExec.GetGeneralParameters() + -- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella + local idTempGroup = BeamLib.CreateTempGroup() + -- Se devo creare la barra if bCreateBar then if #PARTS == 0 then @@ -595,6 +596,7 @@ if bToProcess then PARTS[i].SplittingPoints = BeamLib.GetPartSplittingPoints( PARTS[i]) PARTS[i].NotClampableLength = { STD = { dHead = 0, dTail = 0}, SIDE = { dHead = 0, dTail = 0}, DOWN = { dHead = 0, dTail = 0}} PARTS[i].sBTLInfo = EgtGetInfo( PARTS[i].id, 'PROJ', 's') or nil + PARTS[i].idTempGroup = idTempGroup PARTS[i].sAISetupConfig = EgtGetInfo( PARTS[i].id, 'AISETUP', 's') or ( GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo] and GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo].sAISetupConfig) or -- i parametri BTL potrebbero non esistere @@ -652,16 +654,12 @@ if bToProcess then -- Lavoro le features if not GetDataConfig() then return end - -- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella - BeamLib.CreateTempGroup() - BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) BeamExec.ProcessMachinings( PARTS) -- si cancella gruppo temporaneo contenente entità da cancellare - local idTempGroup = BeamLib.GetTempGroup() - --EgtErase( idTempGroup) + EgtErase( idTempGroup) local sOutput = '' @@ -764,6 +762,11 @@ else end end +-- log tempi di esecuzione +if EgtGetDebugLevel() >= 3 then + TIMER:logAllElapsed() +end + -- *** Eseguo simulazione con verifica collisione in cieco *** if ( BEAM.FLAG == 0 and ( bToProcess or bToRecalc)) or BEAM.FLAG == 3 or BEAM.FLAG == 4 then EgtOutLog( ' +++ Simulating with collision check >>>') diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index a78a556..bbce2dd 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -352,6 +352,9 @@ end -- *** funzioni posizionamento pezzi all'interno della barra *** ------------------------------------------------------------------------------------------------------------- function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bCalcBestPieceUnloadPosition) + -- gruppo per geometrie temporanee + local idTempGroup = BeamLib.GetTempGroup() + -- default per nuove costanti qualora non definite BeamData.OVM_BLADE_HBEAM = ( BeamData.OVM_BLADE_HBEAM or 11) BeamData.OVM_CHAIN_HBEAM = ( BeamData.OVM_CHAIN_HBEAM or 8) @@ -497,6 +500,7 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, b BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig) PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON) PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition) + PARTS[i].idTempGroup = idTempGroup else local sOut = 'Error: part L(' .. EgtNumToString( dPartLen, 1) .. ') too big for raw part L(' .. EgtNumToString( dLen - 0.1, 1) .. ')' diff --git a/LuaLibs/DiceCut.lua b/LuaLibs/DiceCut.lua index 00e9457..14db6ce 100644 --- a/LuaLibs/DiceCut.lua +++ b/LuaLibs/DiceCut.lua @@ -398,7 +398,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters) if OptionalParameters.bSaveAddedGeometries then idAddGroup = BeamLib.GetAddGroup( Part.id) else - idAddGroup = BeamLib.GetTempGroup() + idAddGroup = Part.idTempGroup end -- faccia primaria diff --git a/LuaLibs/FeatureLib.lua b/LuaLibs/FeatureLib.lua index 2c6886c..f86d831 100644 --- a/LuaLibs/FeatureLib.lua +++ b/LuaLibs/FeatureLib.lua @@ -54,7 +54,7 @@ end -- restituisce vero se tutti i lati della faccia passata si trovano sul grezzo local function AreAllFaceEdgesOnRaw( Part, Proc, idFace) local bEdgeOnRaw = true - local idTempGroup = BeamLib.GetTempGroup() + local idTempGroup = Part.idTempGroup local nLoopId, nLoopCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, idTempGroup) if nLoopCnt > 1 then error( 'AreAllFaceEdgesOnRaw : too many loops') diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index afdbd35..fe5e21a 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -13,6 +13,7 @@ local BeamData = require( 'BeamData') local BeamLib = require( 'BeamLib') local FeatureLib = require( 'FeatureLib') local BCS = require( 'BasicCustomerStrategies') +local PreCollisionLib = require( 'PreCollisionLib') local FaceData = require ( 'FaceData') EgtOutLog( ' MachiningLib started', 1) @@ -283,218 +284,6 @@ local function IsFaceZOutOfRange( vtNFace, Tool) return false end -------------------------------------------------------------------------------------------------------------- --- -local function CheckCollisionAxisC( Edge, vtNFace, vtHead, Part, Tool, dDepthToMachine) - - -end - -------------------------------------------------------------------------------------------------------------- --- si controlla la collisione con il carro Z nei 3 piani globali X, Y e Z. Se c'è collisione in tutti i piani, il carro sarà in collisione. -local function CheckCollisionAxisZ( Edge, vtNFace, vtHead, Part, Tool, dDepthToMachine) - - -- se faccia non parallela a direzione testa c'è qualcosa che non va - if not AreSameOrOppositeVectorApprox( vtNFace, vtHead) then - error( 'CheckCollisionAxisZ : invalid directions') - end - - -- TODO rimettere - -- se direzione utensile parallela ad uno degli assi principali non serve alcuna verifica - -- if AreSameOrOppositeVectorApprox( Edge.vtN, X_AX()) - -- or AreSameOrOppositeVectorApprox( Edge.vtN, Y_AX()) - -- or AreSameOrOppositeVectorApprox( Edge.vtN, Z_AX()) then - - -- return false - -- end - - local idTempGroup = BeamLib.GetTempGroup() - - -- punti notevoli della lavorazione in cui fare il check - -- TODO aggiungere anche ptMid? - local MachiningPoints = { - Point3d( Edge.ptStart) + Edge.vtN * ( Edge.dElevation - dDepthToMachine), - Point3d( Edge.ptEnd) + Edge.vtN * ( Edge.dElevation - dDepthToMachine) - } - - -- punti in centro lama su naso mandrino o aggregato. In base a direzione e punto - local bIsDownUp = AreOppositeVectorApprox( vtNFace, vtHead) - local ToolExitPoints = {} - for i = 1, #MachiningPoints do - ToolExitPoints[i] = Point3d( MachiningPoints[i] + Edge.vtN * Tool.dDiameter / 2) + vtHead * EgtIf( bIsDownUp, ( Tool.dLength - Tool.dThickness), Tool.dLength) - end - - -- direzioni in cui fare il check - -- TODO queste cambieranno in base all'asse da controllare - local CheckDirections = { - { vtDirectionX = X_AX(), vtDirectionY = Z_AX(), vtDirectionZ = -Y_AX(), sDirectionName = 'X'}, - { vtDirectionX = Y_AX(), vtDirectionY = Z_AX(), vtDirectionZ = X_AX(), sDirectionName = 'Y'}, - { vtDirectionX = X_AX(), vtDirectionY = Y_AX(), vtDirectionZ = Z_AX(), sDirectionName = 'Z'} - } - - -- TEST - local Color = Color3d( math.random(0, 255), math.random(0, 255), math.random(0, 255)) - -- TEST - - for i = 1, #CheckDirections do - - local vtDirectionX = CheckDirections[i].vtDirectionX - local vtDirectionZ = CheckDirections[i].vtDirectionZ - local sDirectionName = CheckDirections[i].sDirectionName - - -- costruzione flat region del pezzo nel piano scelto - -- si estrae prima la silhouette nel piano - local idFirstCurve, nCurveCount = EgtGetSurfTmSilhouette( Part.idBoxTm, vtDirectionZ, 10 * GEO.EPS_SMALL, idTempGroup, GDB_RT.GLOB) - -- se più curve c'è qualcosa che non va: errore - if nCurveCount > 1 then - error( 'CheckCollisionAxisZ : error in part box') - end - -- creazione flat region dalla silhouette - local idPartSurfFr = EgtSurfFlatRegion( idTempGroup, idFirstCurve) - - -- costruzione flat region del grezzo restante nel piano scelto (con leggera sovrapposizione) - -- si costruisce il box in globale - local ptRestLengthMax = Point3d( Part.b3Part:getMin()) + X_AX() * 500 * GEO.EPS_SMALL - local ptRestLengthMin = Point3d( Part.b3Part:getMin():getX() - 2000, Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ()) - local b3RestLength = BBox3d( ptRestLengthMin, ptRestLengthMax) - -- si crea la trimesh dal box - local idRestLengthBoxTm = EgtSurfTmBBox( idTempGroup, b3RestLength , false, GDB_RT.GLOB) - -- si estrae la silhouette nel piano - idFirstCurve, nCurveCount = EgtGetSurfTmSilhouette( idRestLengthBoxTm, vtDirectionZ, 10 * GEO.EPS_SMALL, idTempGroup, GDB_RT.GLOB) - -- se più curve c'è qualcosa che non va: errore - if nCurveCount > 1 then - error( 'CheckCollisionAxisZ : error in part box') - end - -- creazione flat region dalla silhouette - local idRestLengthSurfFr = EgtSurfFlatRegion( idTempGroup, idFirstCurve) - - -- costruzione flat region del carro Z nel piano scelto, tra punto iniziale e finale lavorazione - -- recupero punti da macchina per costruire flat region - local ZAxisPoints = Tool.SetupInfo.GetAxisZPoints( sDirectionName) - -- per ogni punto in cui controllare si crea una flat region (al momento solo 2, altrimenti la ruled) - local CollisionCurves = {} - for j = 1, #ToolExitPoints do - -- curva di collisione in riferimento locale - local idCollisionCurve = EgtCurveCompoFromPoints( idTempGroup, ZAxisPoints) - table.insert( CollisionCurves, idCollisionCurve) - - -- TEST - EgtSetColor( idCollisionCurve, Color) - -- TEST - - -- calcolo pivot in riferimento globale - local ptRef = ToolExitPoints[j] - local frTool = Frame3d( ptRef, vtHead, Edge.vtN) - -- TODO vtPivotGlob dovrà arrivare da funzione perchè può cambiare con SCC (es: aggregato) - local vtPivotGlob = Vector3d( Tool.SetupInfo.vtPivot) - vtPivotGlob:toGlob( frTool) - local ptPivot = ptRef + vtPivotGlob - EgtPoint( idTempGroup, ptPivot, 0) - - -- curva in riferimento globale - local frReference = Frame3d( ptPivot, vtDirectionZ, vtDirectionX) - EgtTransform( idCollisionCurve, frReference, GDB_RT.GLOB ) - end - -- TODO serve fare la ruled o basta controllare nei punti estremi? - --EgtSurfTmRuled( idTempGroup, CollisionCurves[1], CollisionCurves[2]) - end - - -end - -------------------------------------------------------------------------------------------------------------- --- nel piano perpendicolare alla direzione di taglio, se c'è intersezione tra motore e trave c'è collisione --- TODO da integrare in funzione sopra -local function CheckCollisionAxisAB( Edge, vtNFace, vtHead, Part, Tool, dDepthToMachine) - - -- se direzione utensile parallela ad uno degli assi principali non serve alcuna verifica - if AreSameOrOppositeVectorApprox( Edge.vtN, X_AX()) - or AreSameOrOppositeVectorApprox( Edge.vtN, Y_AX()) - or AreSameOrOppositeVectorApprox( Edge.vtN, Z_AX()) then - - return false - end - - local idTempGroup = BeamLib.GetTempGroup() - - -- riferimento perpendicolare al taglio, X nel verso della normale al lato e Y verso il motore - local ptMachining = Point3d( ( Edge.ptStart + Edge.ptEnd) / 2) + Edge.vtN * ( Edge.dElevation - dDepthToMachine) - local vtEdge = Edge.ptEnd - Edge.ptStart - vtEdge:normalize() - - -- costruzione flat region del pezzo nel piano perpendicolare al taglio - -- si estrae prima la silhouette nel piano - local idFirstCurve, nCurveCount = EgtGetSurfTmSilhouette( Part.idBoxTm, vtEdge, 10 * GEO.EPS_SMALL, idTempGroup, GDB_RT.GLOB) - -- se più curve c'è qualcosa che non va: errore - if nCurveCount > 1 then - error( 'Check2DBladeCollision : error in part box') - end - -- creazione flat region dalla silhouette - local idPartSurfFr = EgtSurfFlatRegion( idTempGroup, idFirstCurve) - - -- costruzione flat region del grezzo restante nel piano perpendicolare al taglio (con leggera sovrapposizione) - -- si costruisce il box in globale - local ptRestLengthMax = Point3d( Part.b3Part:getMin() + X_AX() * 500 * GEO.EPS_SMALL) - local ptRestLengthMin = Point3d( Part.b3Part:getMin():getX() - 2000, Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ()) - local b3RestLength = BBox3d( ptRestLengthMin, ptRestLengthMax) - -- si crea la trimesh dal box - local idRestLengthBoxTm = EgtSurfTmBBox( idTempGroup, b3RestLength , false, GDB_RT.GLOB) - -- si estrae la silhouette nel piano - idFirstCurve, nCurveCount = EgtGetSurfTmSilhouette( idRestLengthBoxTm, vtEdge, 10 * GEO.EPS_SMALL, idTempGroup, GDB_RT.GLOB) - -- se più curve c'è qualcosa che non va: errore - if nCurveCount > 1 then - error( 'Check2DBladeCollision : error in part box') - end - -- creazione flat region dalla silhouette - local idRestLengthSurfFr = EgtSurfFlatRegion( idTempGroup, idFirstCurve) - - -- costruzione flat region approssimata del motore nel piano perpendicolare al taglio - -- punto di congiunzione tra motore e lama - local ptMaxElev = ptMachining + Edge.vtN * Tool.dMaxMaterial - -- se taglio standard (no DownUp) il punto va spostato dello spessore lama - if AreSameVectorApprox( vtNFace, vtHead) then - ptMaxElev = ptMaxElev + vtNFace * Tool.dThickness - end - -- TODO qui sostituire con il valore reale letto dal SetupInfo - -- per Fast si dovrà aggiungere la lunghezza del massimo utensile utilizzabile con lama - local dHeadDepth = 480 - local dHeadWidth = 480 - local ptOpposite = ptMaxElev + Edge.vtN * dHeadWidth - local ptCross = ptOpposite + vtHead * dHeadDepth - local idHeadRectangle = EgtRectangle3P( idTempGroup, ptMaxElev, ptCross, ptOpposite, GDB_RT.GLOB) - -- flat region dal rettangolo - local idHeadSurfFr = EgtSurfFlatRegion( idTempGroup, idHeadRectangle) - - -- intersezione tra pezzo e motore (se fallisce si inverte la flat region del motore, probabile normale opposta) - local bIntersectSuccess = EgtSurfFrIntersect( idPartSurfFr, idHeadSurfFr) - if not bIntersectSuccess then - EgtInvertSurf( idHeadSurfFr) - bIntersectSuccess = EgtSurfFrIntersect( idPartSurfFr, idHeadSurfFr) - end - if not bIntersectSuccess then - error( 'Check2DBladeCollision : intersect fail') - end - - local bCollisionFoundPiece = EgtExistsObj( idPartSurfFr) - - -- intersezione tra grezzo restante e motore, se con il pezzo non c'è collisione - local bCollisionFoundRestLength - if not bCollisionFoundPiece then - bIntersectSuccess = EgtSurfFrIntersect( idRestLengthSurfFr, idHeadSurfFr) - if not bIntersectSuccess then - EgtInvertSurf( idHeadSurfFr) - bIntersectSuccess = EgtSurfFrIntersect( idRestLengthSurfFr, idHeadSurfFr) - end - if not bIntersectSuccess then - error( 'Check2DBladeCollision : intersect fail') - end - - bCollisionFoundRestLength = EgtExistsObj( idRestLengthSurfFr) - end - - return bCollisionFoundPiece, bCollisionFoundRestLength -end - ------------------------------------------------------------------------------------------------------------- -- ritorna se la faccia e il lato sono lavorabili e, se sì, il modo di lavorare (standard/DownUp) -- TODO si dovrà decidere come tagliare anche se pezzo corto (il motore non deve ingombrare con il pinzaggio) @@ -507,9 +296,12 @@ function MachiningLib.GetBladeEngagement( Face, Edge, Part, Tool, dDepthToMachin -- TODO La riduzione percorso cambia questo test? -- TODO da completare questo test - local bCollisionFoundZ, bMoveAfterSplitZ = CheckCollisionAxisZ( Edge, Face.vtN, Face.vtN, Part, Tool, dDepthToMachine) + -- TODO rimuovere timer qua + TIMER:startElapsed( 'CollisionZ') + local bCollisionFoundZ, bMoveAfterSplitZ = PreCollisionLib.CheckCollisionAxisZ( Edge, Face.vtN, Face.vtN, Part, Tool, dDepthToMachine) + TIMER:stopElapsed( 'CollisionZ') - local bCollisionFound, bMoveAfterSplit = CheckCollisionAxisAB( Edge, Face.vtN, Face.vtN, Part, Tool, dDepthToMachine) + local bCollisionFound, bMoveAfterSplit = PreCollisionLib.CheckCollisionAxisAB( Edge, Face.vtN, Face.vtN, Part, Tool, dDepthToMachine) if bCollisionCheckForDownUpOnly or not bCollisionFound then return true, sBladeEngagement, bMoveAfterSplit @@ -535,7 +327,7 @@ function MachiningLib.GetBladeEngagement( Face, Edge, Part, Tool, dDepthToMachin end -- orientamento faccia / utensile compatibili con DownUp: lavorabile - local bCollisionFound, bMoveAfterSplit = CheckCollisionAxisAB( Edge, Face.vtN, -Face.vtN, Part, Tool, dDepthToMachine) + local bCollisionFound, bMoveAfterSplit = PreCollisionLib.CheckCollisionAxisAB( Edge, Face.vtN, -Face.vtN, Part, Tool, dDepthToMachine) if not bCollisionFound then sBladeEngagement = 'DownUp' @@ -714,9 +506,9 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters) if bIsToolCompatible then if FaceToMachine and EdgeToMachine and Part and dElevation then local bIsBladeOk = false - TIMER:setCheckpoint( 'GetBladeEngagement') + TIMER:startElapsed( 'GetBladeEngagement') bIsBladeOk, sCurrentBladeEngagement, bCurrentMoveAfterSplit = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachine, Part, TOOLS[i], dElevation, bCollisionCheckForDownUpOnly) - TIMER:logElapsed( 'GetBladeEngagement') + TIMER:stopElapsed( 'GetBladeEngagement') -- orientamento non raggiungibile if not bIsBladeOk then bIsToolCompatible = false @@ -1597,7 +1389,7 @@ function MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part) local ProcTm = FeatureLib.GetProcFromTrimesh( Machining.Geometry[1][1], Part) local dDepthToMachine = min( ProcTm.Faces[Machining.Geometry[1][2] + 1].dElevation, ( Machining.dMaxElev or ProcTm.Faces[Machining.Geometry[1][2] + 1].dElevation)) - ( max( 0, Machining.dResidualDepth or 0)) local nSteps = max( ceil( ( dDepthToMachine - 50 * GEO.EPS_SMALL) / TOOLS[Machining.nToolIndex].dStep), 1) - local idTempGroup = BeamLib.GetTempGroup() + local idTempGroup = Part.idTempGroup -- TODO in futuro creare flatregion (se ci fossero isole il calcolo del percorso non sarebbe corretto) local idFaceContour = EgtExtractSurfTmFacetLoops( ProcTm.id, Machining.Geometry[1][2], idTempGroup) -- si settano i lati aperti della curva derivata dalla superficie diff --git a/LuaLibs/PreCollisionLib.lua b/LuaLibs/PreCollisionLib.lua new file mode 100644 index 0000000..f653856 --- /dev/null +++ b/LuaLibs/PreCollisionLib.lua @@ -0,0 +1,225 @@ +-- PreCollisionLib.lua by Egalware s.r.l. 2025/11/24 +-- Libreria stima collisioni per travi + +-- Tabella per definizione modulo +local PreCollisionLib = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali + + +EgtOutLog( ' PreCollisionLib started', 1) + + +------------------------------------------------------------------------------------------------------------- +-- costruzione flat region del pezzo nel piano scelto +local function GetPartSurfFrInPlane( Part, vtDirection) + + -- si estrae prima la silhouette nel piano + local idFirstCurve, nCurveCount = EgtGetSurfTmSilhouette( Part.idBoxTm, vtDirection, 10 * GEO.EPS_SMALL, Part.idTempGroup, GDB_RT.GLOB) + -- se più curve c'è qualcosa che non va: errore + if nCurveCount > 1 then + error( 'GetPartSurfFrInPlane : error in part box') + end + -- creazione flat region dalla silhouette + local idPartSurfFr = EgtSurfFlatRegion( Part.idTempGroup, idFirstCurve) + + return idPartSurfFr +end + +------------------------------------------------------------------------------------------------------------- +-- costruzione flat region del grezzo restante nel piano scelto (con leggera sovrapposizione) +local function GetRestlengthSurfFrInPlane( Part, vtDirection) + + -- si costruisce il box in globale + local ptRestLengthMax = Point3d( Part.b3Part:getMin()) + X_AX() * 500 * GEO.EPS_SMALL + local ptRestLengthMin = Point3d( Part.b3Part:getMin():getX() - 2000, Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ()) + local b3RestLength = BBox3d( ptRestLengthMin, ptRestLengthMax) + -- si crea la trimesh dal box + local idRestLengthBoxTm = EgtSurfTmBBox( Part.idTempGroup, b3RestLength , false, GDB_RT.GLOB) + -- si estrae la silhouette nel piano + local idFirstCurve, nCurveCount = EgtGetSurfTmSilhouette( idRestLengthBoxTm, vtDirection, 10 * GEO.EPS_SMALL, Part.idTempGroup, GDB_RT.GLOB) + -- se più curve c'è qualcosa che non va: errore + if nCurveCount > 1 then + error( 'CheckCollisionAxisZ : error in part box') + end + -- creazione flat region dalla silhouette + local idRestlengthSurfFr = EgtSurfFlatRegion( Part.idTempGroup, idFirstCurve) + + return idRestlengthSurfFr +end + +------------------------------------------------------------------------------------------------------------- +-- si controlla la collisione con il carro Z nei 3 piani globali X, Y e Z. Se c'è collisione in tutti i piani, il carro sarà in collisione. +function PreCollisionLib.CheckCollisionAxisZ( Edge, vtNFace, vtHead, Part, Tool, dDepthToMachine) + + -- se faccia non parallela a direzione testa c'è qualcosa che non va + if not AreSameOrOppositeVectorApprox( vtNFace, vtHead) then + error( 'CheckCollisionAxisZ : invalid directions') + end + + -- TODO modificare e rimettere (Hmax pezzo) + -- se direzione utensile parallela ad uno degli assi principali non serve alcuna verifica + -- if AreSameOrOppositeVectorApprox( Edge.vtN, X_AX()) + -- or AreSameOrOppositeVectorApprox( Edge.vtN, Y_AX()) + -- or AreSameOrOppositeVectorApprox( Edge.vtN, Z_AX()) then + + -- return false + -- end + + -- punti notevoli della lavorazione in cui fare il check + local MachiningPoints = { + Edge.ptStart + Edge.vtN * ( Edge.dElevation - dDepthToMachine), + Point3d( ( Edge.ptStart + Edge.ptEnd) / 2) + Edge.vtN * ( Edge.dElevation - dDepthToMachine), + Edge.ptEnd + Edge.vtN * ( Edge.dElevation - dDepthToMachine) + } + + -- punti in centro lama su naso mandrino o aggregato. In base a direzione e punto + local bIsDownUp = AreOppositeVectorApprox( vtNFace, vtHead) + local ToolExitPoints = {} + for i = 1, #MachiningPoints do + ToolExitPoints[i] = Point3d( MachiningPoints[i] + Edge.vtN * Tool.dDiameter / 2) + vtHead * EgtIf( bIsDownUp, ( Tool.dLength - Tool.dThickness), Tool.dLength) + end + + -- direzioni in cui fare il check + -- TODO queste cambieranno in base all'asse da controllare + local CheckDirections = { + { vtDirectionX = X_AX(), vtDirectionY = Z_AX(), vtDirectionZ = -Y_AX(), sDirectionName = 'X'}, + { vtDirectionX = Y_AX(), vtDirectionY = Z_AX(), vtDirectionZ = X_AX(), sDirectionName = 'Y'}, + { vtDirectionX = X_AX(), vtDirectionY = Y_AX(), vtDirectionZ = Z_AX(), sDirectionName = 'Z'} + } + + -- TEST + local Color = Color3d( math.random(0, 255), math.random(0, 255), math.random(0, 255)) + -- TEST + + -- per ogni punto in cui controllare si crea una flat region + local CollisionCurves = {} + + for j = 1, #ToolExitPoints do + + -- calcolo pivot in riferimento globale + local ptRef = ToolExitPoints[j] + local frTool = Frame3d( ptRef, vtHead, Edge.vtN) + -- TODO vtPivotGlob dovrà arrivare da funzione perchè può cambiare con SCC (es: aggregato) + local vtPivotGlob = Vector3d( Tool.SetupInfo.vtPivot) + vtPivotGlob:toGlob( frTool) + local ptPivot = ptRef + vtPivotGlob + + for i = 1, #CheckDirections do + + local vtDirectionX = CheckDirections[i].vtDirectionX + local vtDirectionZ = CheckDirections[i].vtDirectionZ + local sDirectionName = CheckDirections[i].sDirectionName + + -- costruzione flat region del pezzo e del grezzo restante nel piano perpendicolare al taglio + local idPartSurfFr = GetPartSurfFrInPlane( Part, vtDirectionZ) + local idRestLengthSurfFr = GetRestlengthSurfFrInPlane( Part, vtDirectionZ) + + -- costruzione flat region della curva di collisione nel piano scelto, per tutti i punti notevoli scelti + -- recupero punti da macchina per costruire flat region + local ZAxisPoints = Tool.SetupInfo.GetAxisZPoints( sDirectionName) + + -- curva di collisione in riferimento locale + local idCollisionCurve = EgtCurveCompoFromPoints( Part.idTempGroup, ZAxisPoints) + table.insert( CollisionCurves, idCollisionCurve) + + -- TEST + EgtSetColor( idCollisionCurve, Color) + -- TEST + + -- curva in riferimento globale + local frReference = Frame3d( ptPivot, vtDirectionZ, vtDirectionX) + EgtTransform( idCollisionCurve, frReference, GDB_RT.GLOB ) + end + end +end + +------------------------------------------------------------------------------------------------------------- +-- nel piano perpendicolare alla direzione di taglio, se c'è intersezione tra motore e trave c'è collisione +-- TODO da integrare in funzione sopra +function PreCollisionLib.CheckCollisionAxisAB( Edge, vtNFace, vtHead, Part, Tool, dDepthToMachine) + + -- se direzione utensile parallela ad uno degli assi principali non serve alcuna verifica + if AreSameOrOppositeVectorApprox( Edge.vtN, X_AX()) + or AreSameOrOppositeVectorApprox( Edge.vtN, Y_AX()) + or AreSameOrOppositeVectorApprox( Edge.vtN, Z_AX()) then + + return false + end + + -- riferimento perpendicolare al taglio, X nel verso della normale al lato e Y verso il motore + local ptMachining = Point3d( ( Edge.ptStart + Edge.ptEnd) / 2) + Edge.vtN * ( Edge.dElevation - dDepthToMachine) + local vtEdge = Edge.ptEnd - Edge.ptStart + vtEdge:normalize() + + -- costruzione flat region del pezzo e del grezzo restante nel piano perpendicolare al taglio + local idPartSurfFr = GetPartSurfFrInPlane( Part, vtEdge) + local idRestlengthSurfFr = GetRestlengthSurfFrInPlane( Part, vtEdge) + + -- costruzione flat region approssimata del motore nel piano perpendicolare al taglio + -- punto di congiunzione tra motore e lama + local ptMaxElev = ptMachining + Edge.vtN * Tool.dMaxMaterial + -- se taglio standard (no DownUp) il punto va spostato dello spessore lama + if AreSameVectorApprox( vtNFace, vtHead) then + ptMaxElev = ptMaxElev + vtNFace * Tool.dThickness + end + -- TODO qui sostituire con il valore reale letto dal SetupInfo + -- per Fast si dovrà aggiungere la lunghezza del massimo utensile utilizzabile con lama + local dHeadDepth = 480 + local dHeadWidth = 480 + local ptOpposite = ptMaxElev + Edge.vtN * dHeadWidth + local ptCross = ptOpposite + vtHead * dHeadDepth + local idHeadRectangle = EgtRectangle3P( Part.idTempGroup, ptMaxElev, ptCross, ptOpposite, GDB_RT.GLOB) + -- flat region dal rettangolo + local idHeadSurfFr = EgtSurfFlatRegion( Part.idTempGroup, idHeadRectangle) + + -- intersezione tra pezzo e motore (se fallisce si inverte la flat region del motore, probabile normale opposta) + local bIntersectSuccess = EgtSurfFrIntersect( idPartSurfFr, idHeadSurfFr) + if not bIntersectSuccess then + EgtInvertSurf( idHeadSurfFr) + bIntersectSuccess = EgtSurfFrIntersect( idPartSurfFr, idHeadSurfFr) + end + if not bIntersectSuccess then + error( 'Check2DBladeCollision : intersect fail') + end + + local bCollisionFoundPiece = EgtExistsObj( idPartSurfFr) + + -- intersezione tra grezzo restante e motore, se con il pezzo non c'è collisione + local bCollisionFoundRestLength + if not bCollisionFoundPiece then + bIntersectSuccess = EgtSurfFrIntersect( idRestlengthSurfFr, idHeadSurfFr) + if not bIntersectSuccess then + EgtInvertSurf( idHeadSurfFr) + bIntersectSuccess = EgtSurfFrIntersect( idRestlengthSurfFr, idHeadSurfFr) + end + if not bIntersectSuccess then + error( 'Check2DBladeCollision : intersect fail') + end + + bCollisionFoundRestLength = EgtExistsObj( idRestlengthSurfFr) + end + + return bCollisionFoundPiece, bCollisionFoundRestLength +end + + + + + + + + + + + + + + + + + +return PreCollisionLib \ No newline at end of file diff --git a/LuaLibs/TimeLib.lua b/LuaLibs/TimeLib.lua index 96f8f62..b4ea056 100644 --- a/LuaLibs/TimeLib.lua +++ b/LuaLibs/TimeLib.lua @@ -12,59 +12,111 @@ EgtOutLog( ' TimeLib started', 1) TimeLib.__index = TimeLib function TimeLib.new() - local self = setmetatable({}, TimeLib) - self.dStartTime = os.clock() - self.Checkpoints = {} -- each checkpoint stores first and last timestamps - return self + local TimeLibInstance = setmetatable({}, TimeLib) + TimeLibInstance.dStartTime = os.clock() + TimeLibInstance.Measurements = {} + return TimeLibInstance end --- reset timer +-- reset entire timer function TimeLib:start() self.dStartTime = os.clock() - self.Checkpoints = {} + self.Measurements = {} end --- setta un checkpoint con nome (default se non specificato) -function TimeLib:setCheckpoint( sName) - local sCpName = sName or "default" - local dNow = os.clock() +-- start elapsed measurement for a specific name +function TimeLib:startElapsed(sName) + local sMeasurementName = sName or "Default" + local dNow = os.clock() - if not self.Checkpoints[sCpName] then - self.Checkpoints[sCpName] = { dFirst = dNow, dLast = dNow } - else - self.Checkpoints[sCpName].dLast = dNow - end + if not self.Measurements[sMeasurementName] then + self.Measurements[sMeasurementName] = { + dStart = dNow, + dLast = 0, + dCumulative = 0, + dRecent = 0, + nCount = 0 + } + else + self.Measurements[sMeasurementName].dStart = dNow + end end --- ritorna il tempo trascorso --- se settato un checkpoint, ritorna anche il tempo di quel checkpoint, cumulativo (dal primo checkpoint settato con quel nome) e recente (dall'ultimo checkpoint settato) -function TimeLib:elapsed( sCheckpointName) - local dTotal = os.clock() - self.dStartTime - local sCpName = sCheckpointName or "default" - local Checkpoint = self.Checkpoints[sCpName] +-- stop elapsed measurement (increments count and updates cumulative) +function TimeLib:stopElapsed(sName) + local sMeasurementName = sName or "Default" + local dNow = os.clock() + local Measurement = self.Measurements[sMeasurementName] - if Checkpoint then - local dCumulative = os.clock() - Checkpoint.dFirst - local dRecent = os.clock() - Checkpoint.dLast - return dTotal, dCumulative, dRecent - else - return dTotal, nil, nil - end + if Measurement and Measurement.dStart then + local dDuration = dNow - Measurement.dStart + Measurement.dRecent = dDuration + Measurement.dCumulative = Measurement.dCumulative + dDuration + Measurement.dLast = dNow + Measurement.nCount = Measurement.nCount + 1 + Measurement.dStart = nil + else + -- if stop called without start, initialize with zero + self.Measurements[sMeasurementName] = { + dStart = nil, + dLast = dNow, + dCumulative = 0, + dRecent = 0, + nCount = 0 + } + end end --- log del tempo trascorso, come sopra -function TimeLib:logElapsed( sCheckpointName) - local dTotal, dCumulative, dRecent = self:elapsed( sCheckpointName) - local sCpName = sCheckpointName or "default" +-- reset elapsed for a specific measurement +function TimeLib:resetElapsed(sName) + local sMeasurementName = sName or "Default" + self.Measurements[sMeasurementName] = nil +end - if dCumulative then - EgtOutLog( string.format( - "%s time: recent %.3f, cumulative %.3f, total %.3f", - sCpName, dRecent, dCumulative, dTotal)) - else - EgtOutLog( string.format("Total %.3f (no checkpoint '%s' set)", - dTotal, sCpName)) - end +-- return elapsed times: total, cumulative, recent, count +function TimeLib:getElapsed(sName) + local dTotal = os.clock() - self.dStartTime + local sMeasurementName = sName or "Default" + local Measurement = self.Measurements[sMeasurementName] + + if Measurement then + return dTotal, Measurement.dCumulative, Measurement.dRecent, Measurement.nCount + else + return dTotal, nil, nil, 0 + end +end + +-- log elapsed times for one measurement +function TimeLib:logElapsed(sName) + local dTotal, dCumulative, dRecent, nCount = self:getElapsed(sName) + local sMeasurementName = sName or "Default" + + if dCumulative then + EgtOutLog(string.format( + "%s(#%d): recent %.3f, cumulative %.3f, total %.3f", + sMeasurementName, nCount, dRecent, dCumulative, dTotal)) + else + EgtOutLog(string.format("Total %.3f (no '%s' measurement started)", + dTotal, sMeasurementName)) + end +end + +-- log elapsed times for all measurements +function TimeLib:logAllElapsed() + local dTotal = os.clock() - self.dStartTime + if next(self.Measurements) == nil then + EgtOutLog(string.format("Total %.3f (no measurements started)", dTotal)) + return + end + + for sMeasurementName, Measurement in pairs(self.Measurements) do + local dCumulative = Measurement.dCumulative + local dRecent = Measurement.dRecent + local nCount = Measurement.nCount + EgtOutLog(string.format( + "%s(#%d): recent %.3f, cumulative %.3f, total %.3f", + sMeasurementName, nCount, dRecent, dCumulative, dTotal)) + end end return TimeLib diff --git a/Process.lua b/Process.lua index 961be4f..ce5a431 100644 --- a/Process.lua +++ b/Process.lua @@ -302,8 +302,6 @@ end -- *** Inserimento delle lavorazioni nelle travi *** ------------------------------------------------------------------------------------------------------------- local function MyProcessFeatures() - -- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella - local idTempGroup = BeamLib.CreateTempGroup() BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition) BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition) @@ -350,6 +348,7 @@ local function MyProcessFeatures() end -- cancello gruppo temporaneo + local idTempGroup = BeamLib.GetTempGroup() EgtErase( idTempGroup) if #sOutput > 0 then EgtOutLog( sOutput) end @@ -369,10 +368,8 @@ end ------------------------------------------------------------------------------------------------------------- -- calcolo tempo esecuzione -if EgtGetDebugLevel() >= 3 then - TIMER:start() - EgtOutLog( ' Execution timer started') -end +TIMER:start() +EgtOutLog( ' Execution timer started') -- script principale @@ -381,6 +378,9 @@ if not MyProcessInputData() then return end -- recupero parametri generali da progetto BeamExec.GetGeneralParameters() +-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella +BeamLib.CreateTempGroup() + if not MyProcessBeams() then return end if not GetDataConfig() then return end @@ -389,3 +389,9 @@ if not GetDataConfig() then return end EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1') if not MyProcessFeatures() then return end + +-- log tempi di esecuzione +if EgtGetDebugLevel() >= 3 then + TIMER:logAllElapsed() +end + diff --git a/Strategies/Standard/STR0002/STR0002.lua b/Strategies/Standard/STR0002/STR0002.lua index eda5f52..bbc2542 100644 --- a/Strategies/Standard/STR0002/STR0002.lua +++ b/Strategies/Standard/STR0002/STR0002.lua @@ -432,7 +432,7 @@ local function GetSplitSurfaces( Proc, Part, bAddMachining) if bAddMachining then idAddGroup = BeamLib.GetAddGroup( Part.id) else - idAddGroup = BeamLib.GetTempGroup() + idAddGroup = Part.idTempGroup end local nOriginalTmIdTunnel = GDB_ID.NULL if Proc.MainFaces.TunnelAddedFaces then diff --git a/Strategies/Standard/STR0015/STR0015.lua b/Strategies/Standard/STR0015/STR0015.lua index 1be1101..448d5b6 100644 --- a/Strategies/Standard/STR0015/STR0015.lua +++ b/Strategies/Standard/STR0015/STR0015.lua @@ -112,7 +112,7 @@ local function GetRoughStrategy( Proc, Part, bSaveAddedGeometries) if bSaveAddedGeometries then idAddGroup = BeamLib.GetAddGroup( Part.id) else - idAddGroup = BeamLib.GetTempGroup() + idAddGroup = Part.idTempGroup end -- aggiungo piano di sgrossatura e lo lavoro local ptStart, vtNP = GetSawCutData( Proc, Proc.idAddAuxGeom, vtNF, vtN) diff --git a/StrategyLibs/BLADETOWASTE.lua b/StrategyLibs/BLADETOWASTE.lua index 00f5e15..4327116 100644 --- a/StrategyLibs/BLADETOWASTE.lua +++ b/StrategyLibs/BLADETOWASTE.lua @@ -17,7 +17,6 @@ local DiceCut = require( 'DiceCut') -- strategie di base local FaceByBlade = require('FACEBYBLADE') --- tabella per definizione modulo local FeatureInfo = {} ------------------------------------------------------------------------------------------------------------- @@ -561,9 +560,9 @@ local function GetDualSideCutStrategy( Proc, Part, OptionalParameters) -- lavorando dalla direzione opposta si verifica come se si lavorasse il lato opposto local EdgeToMachineOpposite = BeamLib.FindEdgeBestOrientedAsDirection( FaceToMachine.Edges, -EdgeToMachine.vtN) - TIMER:setCheckpoint( 'GetBladeEngagement') + TIMER:startElapsed( 'GetBladeEngagement') local bIsApplicableOpposite = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachineOpposite, Part, TOOLS[ToolInfo.nToolIndex], dDepthToMachine) - TIMER:logElapsed( 'GetBladeEngagement') + TIMER:stopElapsed( 'GetBladeEngagement') if not bIsApplicableOpposite then return CuttingParametersList, EdgeToMachine end @@ -1047,7 +1046,7 @@ function BLADETOWASTE.Make( ProcOrId, Part, OptionalParameters) if bSaveAddedGeometries then idAddGroup = BeamLib.GetAddGroup( Part.id) else - idAddGroup = BeamLib.GetTempGroup() + idAddGroup = Part.idTempGroup end local idFace1 = EgtSurfTmPlaneInBBox( idAddGroup, Proc.Faces[1].ptCenter, Proc.Faces[1].vtN, Part.b3Part, GDB_ID.ROOT) local idFace2 = EgtSurfTmPlaneInBBox( idAddGroup, Proc.Faces[2].ptCenter, Proc.Faces[2].vtN, Part.b3Part, GDB_ID.ROOT) diff --git a/StrategyLibs/FACEBYBLADE.lua b/StrategyLibs/FACEBYBLADE.lua index 3a51f6f..8772d7c 100644 --- a/StrategyLibs/FACEBYBLADE.lua +++ b/StrategyLibs/FACEBYBLADE.lua @@ -273,9 +273,9 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar if nToolIndex then Cutting.nToolIndex = nToolIndex - TIMER:setCheckpoint( 'GetBladeEngagement') + TIMER:startElapsed( 'GetBladeEngagement') Cutting.bIsApplicable, Cutting.sBladeEngagement, Cutting.bMoveAfterSplit = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachine, Part, TOOLS[Cutting.nToolIndex], dDepthToMachine, bCollisionCheckForDownUpOnly) - TIMER:logElapsed( 'GetBladeEngagement') + TIMER:stopElapsed( 'GetBladeEngagement') -- utensile da cercare: si prende la lama migliore che può effettuare questo taglio, senza particolari analisi else @@ -356,9 +356,9 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar if OppositeToolDirectionMode ~= 'Disabled' then -- lavorando dalla direzione opposta si verifica come se si lavorasse il lato opposto - TIMER:setCheckpoint( 'GetBladeEngagement') + TIMER:startElapsed( 'GetBladeEngagement') local bIsApplicableOpposite, sBladeEngagementOpposite, bMoveAfterSplit = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachineOpposite, Part, TOOLS[Cutting.nToolIndex], dDepthToMachine, bCollisionCheckForDownUpOnly) - TIMER:logElapsed( 'GetBladeEngagement') + TIMER:stopElapsed( 'GetBladeEngagement') -- taglio opposto non fattibile if not bIsApplicableOpposite then @@ -453,9 +453,9 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar if OppositeToolDirectionMode == 'Enabled' then EdgeToMachineForEngagement = EdgeToMachineOpposite end - TIMER:setCheckpoint( 'GetBladeEngagement') + TIMER:startElapsed( 'GetBladeEngagement') local bIsApplicable, sBladeEngagement, bMoveAfterSplit = MachiningLib.GetBladeEngagement( FaceToMachine, EdgeToMachineForEngagement, Part, TOOLS[Cutting.nToolIndex], dDepthToMachine) - TIMER:logElapsed( 'GetBladeEngagement') + TIMER:stopElapsed( 'GetBladeEngagement') -- se non fattibile o cambiano le condizioni BladeEngagement, non si riduce if not ( bIsApplicable and ( sBladeEngagement == Cutting.sBladeEngagement) and ( bMoveAfterSplit == Cutting.bMoveAfterSplit)) then