-- PreSimulationLib.lua by Egalware s.r.l. 2025/11/24 -- Libreria stima collisioni per travi -- Tabella per definizione modulo local PreSimulationLib = {} -- Include require( 'EgtBase') local BeamLib = require( 'BeamLib') local BeamData = require( 'BeamDataNew') -- Carico i dati globali EgtOutLog( ' PreSimulationLib started', 1) ------------------------------------------------------------------------------------------------------------- -- costruzione trimesh del grezzo restante (con leggera sovrapposizione) local function GetRestlengthSurfTm( Part) -- 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) return idRestLengthBoxTm end ------------------------------------------------------------------------------------------------------------- -- calcolo pivot in riferimento globale local function GetGlobalPivot( ptRef, vtC, vtHead, vtMovePivot) -- frame solidale all'utensile (lo stesso in cui vtMovePivot è definito) local frTool = Frame3d( ptRef, vtHead, vtC) local vtMovePivotGlob = Vector3d( vtMovePivot) vtMovePivotGlob:toGlob( frTool) local ptPivot = ptRef + vtMovePivotGlob return ptPivot end ------------------------------------------------------------------------------------------------------------- -- restituisce i punti notevoli della lavorazioni in cui fare il controllo local function GetMachiningPoints( Edge, dDepthToMachine) local MachiningPoints = {} -- punti notevoli local ptStart = Edge.ptStart + Edge.vtN * ( Edge.dElevation - dDepthToMachine) local ptEnd = Edge.ptEnd + Edge.vtN * ( Edge.dElevation - dDepthToMachine) local ptMid = Point3d( ( ptStart + ptEnd) / 2) -- caso ottimizzato: lato parallelo ad una direzione principale local vtEdge = Edge.ptEnd - Edge.ptStart vtEdge:normalize() local bIsEdgeParallelToMainDirection = AreSameOrOppositeVectorApprox( vtEdge, X_AX()) or AreSameOrOppositeVectorApprox( vtEdge, Y_AX()) or AreSameOrOppositeVectorApprox( vtEdge, Z_AX()) -- aggiunta punti -- inizio e fine solo se lato obliquo if not bIsEdgeParallelToMainDirection then table.insert( MachiningPoints, ptStart) end table.insert( MachiningPoints, ptMid) if not bIsEdgeParallelToMainDirection then table.insert( MachiningPoints, ptEnd) end return MachiningPoints end ------------------------------------------------------------------------------------------------------------- local function CheckCollisionPoint( ptPointToCheck, vtC, vtHead, PreCollisionData, Part, bCheckOnlyRestlength) local ptPivot = GetGlobalPivot( ptPointToCheck, vtC, vtHead, PreCollisionData.vtMovePivot) -- orientamento del riferimento locale local vtDirectionX = PreCollisionData.Directions.vtDirectionX local vtDirectionY = PreCollisionData.Directions.vtDirectionY local vtDirectionZ = PreCollisionData.Directions.vtDirectionZ -- costruzione trimesh a partire dalla curva di collisione -- recupero punti da macchina per costruire trimesh local CollisionCurvePoints = PreCollisionData.Points -- curva di collisione in riferimento locale local idCollisionCurve = EgtCurveCompoFromPoints( Part.idTempGroup, CollisionCurvePoints) -- curva in riferimento globale local frReference = Frame3d( ptPivot, vtDirectionZ, vtDirectionX) EgtTransform( idCollisionCurve, frReference, GDB_RT.GLOB) -- trimesh di collisione local idCollisionSurfTm if PreCollisionData.bSurfTmByRevolve then idCollisionSurfTm = EgtSurfTmByRevolve( Part.idTempGroup, idCollisionCurve, ptPivot, vtDirectionY, true, 0.05, GDB_RT.GLOB) else local vtPreMove = -vtDirectionZ * ( PreCollisionData.dExtrusionDepth / 2) EgtMove( idCollisionCurve, vtPreMove, GDB_RT.GLOB) local vtExtrusion = vtDirectionZ * PreCollisionData.dExtrusionDepth idCollisionSurfTm = EgtSurfTmByRegionExtrusion( Part.idTempGroup, idCollisionCurve, vtExtrusion, 0.05, GDB_RT.GLOB) end -- check collisione con pezzo local bCollisionFoundPiece = false if not bCheckOnlyRestlength then bCollisionFoundPiece = EgtTestSurfaceSurface( Part.idBoxTm, idCollisionSurfTm, BeamData.COLL_SIC) if not type( bCollisionFoundPiece) == "boolean" then error( 'EgtTestSurfaceSurface fail') end if EgtGetDebugLevel() >= 3 and bCollisionFoundPiece then EgtSetColor( idCollisionSurfTm, RED()) end -- se trovata collisione con pezzo è inutile procedere con il grezzo if bCollisionFoundPiece then return true end end -- check collisione con grezzo restante, se con il pezzo non c'è collisione local bCollisionFoundRestLength = false if not bCollisionFoundPiece then local idRestLengthSurfFr = GetRestlengthSurfTm( Part) bCollisionFoundRestLength = EgtTestSurfaceSurface( idRestLengthSurfFr, idCollisionSurfTm, BeamData.COLL_SIC) if not type( bCollisionFoundRestLength) == "boolean" then error( 'EgtTestSurfaceSurface fail') end if EgtGetDebugLevel() >= 3 and bCollisionFoundRestLength then EgtSetColor( idCollisionSurfTm, ORANGE()) end end return false, bCollisionFoundRestLength end ------------------------------------------------------------------------------------------------------------- -- controllo collisione con verifica intersezione trimesh e geometrie da macchina function PreSimulationLib.CheckCollisionWithAxis( sAxis, MachiningParameters, OptionalParameters) -- parametri obbligatori local Edge = MachiningParameters.Edge local vtNFace = MachiningParameters.vtNFace local vtHead = MachiningParameters.vtHead local Part = MachiningParameters.Part local Tool = MachiningParameters.Tool local dDepthToMachine = MachiningParameters.dDepthToMachine -- parametri opzionali OptionalParameters = OptionalParameters or {} local bCheckOnlyRestlength = OptionalParameters.bCheckOnlyRestlength or false -- se normale faccia non parallela a direzione testa c'è qualcosa che non va if not AreSameOrOppositeVectorApprox( vtNFace, vtHead) then error( 'CheckCollisionWithAxis : 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 = OptionalParameters.MachiningPoints or GetMachiningPoints( Edge, 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 -- vtC punta sempre verso il corpo dell'asse C o verso l'aggregato local vtEdge = Edge.ptEnd - Edge.ptStart vtEdge:normalize() local nSCC = Tool.SetupInfo.GetSCC( Edge.vtN, vtEdge, vtNFace) local vtSCC = BeamLib.GetDirectionFromSCC( nSCC) local vtC = vtHead ^ Tool.SetupInfo.vtRotationAxisC vtC:normalize() if vtC:isZero() then vtC = vtSCC elseif vtC * vtSCC < GEO.EPS_SMALL then vtC = -vtC end -- punti curva collisione e direzioni check da macchina local PreCollisionData = Tool.SetupInfo.GetPreCollisionData( sAxis, vtC, vtHead) local bMoveAfterSplit = false -- se almeno in un punto c'è collisione con il pezzo si ritorna collisione -- se non si trova collisione si ritorna se è necessario separare prima di effettuare la lavorazione (ossia non c'è collisione con il pezzo ma c'è con il grezzo restante) for i = 1, #ToolExitPoints do local bCollisionFoundPiece, bCollisionFoundRestLength = CheckCollisionPoint( ToolExitPoints[i], vtC, vtHead, PreCollisionData, Part, bCheckOnlyRestlength) -- se trovata collisione con pezzo è inutile controllare gli altri punti if bCollisionFoundPiece then return true -- se trovata collisione con grezzo si setta che la lavorazione è da fare dopo separazione e si prosegue con gli altri punti elseif bCollisionFoundRestLength then bMoveAfterSplit = true end end -- se si arriva qui significa che non è stata trovata alcuna collisione con pezzo return false, bMoveAfterSplit end ------------------------------------------------------------------------------------------------------------- -- nel piano perpendicolare alla direzione di taglio, se c'è intersezione tra motore e trave c'è collisione -- ATTENZIONE NON PIU' USATA, verificare ed eliminare function PreSimulationLib.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 local bCollisionFoundPiece = not EgtSurfFrTestExternal( idPartSurfFr, idHeadSurfFr) -- intersezione tra grezzo restante e motore, se con il pezzo non c'è collisione local bCollisionFoundRestLength if not bCollisionFoundPiece then bCollisionFoundRestLength = not EgtSurfFrTestExternal( idRestlengthSurfFr, idHeadSurfFr) end return bCollisionFoundPiece, bCollisionFoundRestLength end return PreSimulationLib