Files
databeamnew/LuaLibs/PreSimulationLib.lua
T

367 lines
15 KiB
Lua

-- 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')
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 punto sull'uscita testa a partire dal punto di lavorazione o di attacco sul diametro utensile
local function GetToolExitPoint( ptMachining, vtNEdge, vtHead, Tool, bIsDownUp)
local ptToolExitPoint = Point3d( ptMachining + vtNEdge * Tool.dDiameter / 2) + vtHead * EgtIf( bIsDownUp, ( Tool.dLength - Tool.dThickness), Tool.dLength)
return ptToolExitPoint
end
-------------------------------------------------------------------------------------------------------------
-- calcolo pivot in riferimento globale, datipunto sull'uscita utensile e direzioni
local function GetGlobalPivot( ptToolExit, vtC, vtHead, vtMovePivot)
-- frame solidale all'utensile (lo stesso in cui vtMovePivot è definito)
local frTool = Frame3d( ptToolExit, vtHead, vtC)
local vtMovePivotGlob = Vector3d( vtMovePivot)
vtMovePivotGlob:toGlob( frTool)
local ptPivot = ptToolExit + vtMovePivotGlob
return ptPivot
end
-------------------------------------------------------------------------------------------------------------
-- restituisce i punti notevoli della lavorazioni in cui fare il controllo
local function GetPointsToCheck( Edge, dDepthToMachine)
local PointsToCheck = {}
-- 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 bIsEdgeParallelToMainDirection =
AreSameOrOppositeVectorApprox( Edge.vtEdge, X_AX())
or AreSameOrOppositeVectorApprox( Edge.vtEdge, Y_AX())
or AreSameOrOppositeVectorApprox( Edge.vtEdge, Z_AX())
-- aggiunta punti
-- inizio e fine solo se lato obliquo
if not bIsEdgeParallelToMainDirection then
table.insert( PointsToCheck, ptStart)
end
table.insert( PointsToCheck, ptMid)
if not bIsEdgeParallelToMainDirection then
table.insert( PointsToCheck, ptEnd)
end
return PointsToCheck
end
-------------------------------------------------------------------------------------------------------------
local function CheckOutOfStrokePoint( ptToolExitToCheck, vtC, vtHead, PreCollisionData)
local bOutOfStroke = false
local ptPivot = GetGlobalPivot( ptToolExitToCheck, vtC, vtHead, PreCollisionData.vtMovePivot)
return bOutOfStroke
end
-------------------------------------------------------------------------------------------------------------
-- check finecorsa: se non vengono passati punti si controllano inizio e fine del lato
function PreSimulationLib.CheckOutOfStroke( Parameters, OptionalParameters )
-- parametri obbligatori
local Edge = Parameters.Edge
local vtNFace = Parameters.vtNFace
local vtHead = Parameters.vtHead
local Tool = Parameters.Tool
-- parametri opzionali
OptionalParameters = OptionalParameters or {}
local PointsToCheck = OptionalParameters.PointsToCheck or { Edge.ptStart, Edge.ptEnd}
local bIsDownUp = AreOppositeVectorApprox( vtNFace, vtHead)
-- punti curva collisione e direzioni check da macchina
-- TODO serve pivot???
local vtMovePivot = nil
-- check collisione sui punti in centro lama su naso mandrino o aggregato. In base a direzione e punto
for i = 1, #PointsToCheck do
local ToolExitPoint = GetToolExitPoint( PointsToCheck[i], Edge.vtN, vtHead, Tool, bIsDownUp)
--local bOutOfStroke = CheckOutOfStrokePoint( ptToolExitToCheck, vtC, vtHead, vtMovePivot)
-- se trovato finecorsa inutile procedere con gli altri punti
if bOutOfStroke then
return true
end
end
-- arrivati qui nessun finecorsa
return false
end
-------------------------------------------------------------------------------------------------------------
local function CheckCollisionPoint( ptToolExitToCheck, vtC, vtHead, PreCollisionData, Part, bCheckOnlyRestlength)
local ptPivot = GetGlobalPivot( ptToolExitToCheck, 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
local function 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 PointsToCheck = OptionalParameters.PointsToCheck or GetPointsToCheck( 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, #PointsToCheck do
ToolExitPoints[i] = GetToolExitPoint( PointsToCheck[i], Edge.vtN, vtHead, Tool, bIsDownUp)
end
-- vtC punta sempre verso il corpo dell'asse C o verso l'aggregato
local nSCC = Tool.SetupInfo.GetSCC( Edge.vtN, Edge.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
-------------------------------------------------------------------------------------------------------------
function PreSimulationLib.CheckCollision( sBladeEngagement, Parameters, OptionalParameters)
local bCollisionFound
local bMoveAfterSplitZ, bMoveAfterSplitC, bMoveAfterSplitAB
-- parametri opzionali, in parte da far transitare
OptionalParameters = OptionalParameters or {}
local OptionalParametersCheckCollisionWithAxis = {}
OptionalParametersCheckCollisionWithAxis.bCheckOnlyRestlength = false
OptionalParametersCheckCollisionWithAxis.PointsToCheck = OptionalParameters.PointsToCheck or nil
-- asse Z si controlla sempre
bCollisionFound, bMoveAfterSplitZ = CheckCollisionWithAxis( 'Z', Parameters, OptionalParametersCheckCollisionWithAxis)
-- se cubetti in modalità standard (no DownUp), gli assi AB e C si controllano solo con grezzo (ci sarebbe collisione con il materiale già rimosso controllando AB e C con pezzo)
if sBladeEngagement == 'Standard' then
OptionalParametersCheckCollisionWithAxis.bCheckOnlyRestlength = OptionalParameters.bIsDicing or false
end
if not bCollisionFound then
bCollisionFound, bMoveAfterSplitAB = CheckCollisionWithAxis( 'AB', Parameters, OptionalParametersCheckCollisionWithAxis)
end
if not bCollisionFound then
bCollisionFound, bMoveAfterSplitC = CheckCollisionWithAxis( 'C', Parameters, OptionalParametersCheckCollisionWithAxis)
end
local bMoveAfterSplit = bMoveAfterSplitZ or bMoveAfterSplitC or bMoveAfterSplitAB
return bCollisionFound, 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)
-- costruzione flat region del pezzo e del grezzo restante nel piano perpendicolare al taglio
local idPartSurfFr = GetPartSurfFrInPlane( Part, Edge.vtEdge)
local idRestlengthSurfFr = GetRestlengthSurfFrInPlane( Part, Edge.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