Files
databeamnew/LuaLibs/PreCollisionLib.lua
T

283 lines
12 KiB
Lua

-- 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( 'Error in part box')
end
-- creazione flat region dalla silhouette
local idRestlengthSurfFr = EgtSurfFlatRegion( Part.idTempGroup, idFirstCurve)
return idRestlengthSurfFr
end
-------------------------------------------------------------------------------------------------------------
-- calcolo pivot in riferimento globale
local function GetGlobalPivot( ptRef, vtSCC, vtHead, vtMovePivot)
-- frame solidale all'utensile (lo stesso in cui vtPivot è definito)
local frTool = Frame3d( ptRef, vtHead, vtSCC)
-- TODO vtPivotGlob dovrà arrivare da funzione perchè può cambiare con SCC (es: aggregato)
local vtPivotGlob = Vector3d( vtMovePivot)
vtPivotGlob:toGlob( frTool)
local ptPivot = ptRef + vtPivotGlob
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
-------------------------------------------------------------------------------------------------------------
-- si controlla la collisione con il carro Z nei 3 piani principali dell'asse sAxis. Se c'è collisione in tutti i piani, l'asse sarà in collisione.
function PreCollisionLib.CheckCollisionWithAxis( sAxis, Edge, vtNFace, vtHead, Part, Tool, dDepthToMachine)
-- 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 = 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
-- TODO questo va girato di verso in base a SCC
local vtSCC = Edge.vtN
-- direzioni in cui fare il check
local PreCollisionData = Tool.SetupInfo.GetPreCollisionData( sAxis, vtSCC, vtHead)
local bMoveAfterSplit = false
-- nel singolo punto notevole si ha collisione se si trova intersezione in tutte le direzioni
-- 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 nCollisionCountPiece = 0
local nCollisionCountRestlength = 0
for j = 1, #PreCollisionData do
-- pivot in globale
local ptPivot = GetGlobalPivot( ToolExitPoints[i], vtSCC, vtHead, PreCollisionData[j].vtMovePivot)
-- orientamento del riferimento locale
local vtDirectionX = PreCollisionData[j].Directions.vtDirectionX
local vtDirectionZ = PreCollisionData[j].Directions.vtDirectionZ
-- costruzione flat region della curva di collisione nel piano scelto
-- recupero punti da macchina per costruire flat region
local CollisionCurvePoints = PreCollisionData[j].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 )
-- flat region di collisione
local idCollisionSurfFr = EgtSurfFlatRegion( Part.idTempGroup, idCollisionCurve)
-- check collisione con pezzo (per la collisione deve esserci intersezione su tutti e 3 i piani)
-- si controlla solo se nelle direzioni precedenti è stata trovata collisione col pezzo,
-- altrimenti significa che non si è usciti dal ciclo solamente per la collisione con grezzo per restituire bMoveAfterSplit
local bCollisionFoundPiece = false
if nCollisionCountPiece == j - 1 then
local idPartSurfFr = GetPartSurfFrInPlane( Part, vtDirectionZ)
bCollisionFoundPiece = not EgtSurfFrTestExternal( idPartSurfFr, idCollisionSurfFr)
if EgtGetDebugLevel() >= 3 and bCollisionFoundPiece then
EgtSetColor( idCollisionSurfFr, RED())
end
end
-- check collisione con grezzo restante, se con il pezzo non c'è collisione
local bCollisionFoundRestLength = false
if not bCollisionFoundPiece then
local idRestLengthSurfFr = GetRestlengthSurfFrInPlane( Part, vtDirectionZ)
bCollisionFoundRestLength = not EgtSurfFrTestExternal( idRestLengthSurfFr, idCollisionSurfFr)
if EgtGetDebugLevel() >= 3 and bCollisionFoundRestLength then
EgtSetColor( idCollisionSurfFr, ORANGE())
end
end
-- se non trovata collisione si passa al punto successivo
if not ( bCollisionFoundPiece or bCollisionFoundRestLength) then
nCollisionCountPiece = 0
nCollisionCountRestlength = 0
break
-- altrimenti si aggiorna il numero di collisioni con pezzo e con grezzo restante
elseif bCollisionFoundPiece then
nCollisionCountPiece = nCollisionCountPiece + 1
elseif bCollisionFoundRestLength then
nCollisionCountRestlength = nCollisionCountRestlength + 1
end
end
-- collisione trovata
if nCollisionCountPiece == #PreCollisionData then
return true, nil
-- nessuna collisione trovata con pezzo ma serve separazione
elseif nCollisionCountRestlength == #PreCollisionData 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
-- 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
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 PreCollisionLib