314 lines
7.9 KiB
Lua
314 lines
7.9 KiB
Lua
-- EgtBBox3d.lua by EgalTech s.r.l. 2021/12/26
|
|
|
|
-- Tavola per definizione modulo (serve ma non usata)
|
|
local EgtBBox3d = {}
|
|
|
|
EgtOutLog( 'EgtBBox3d started', 1)
|
|
|
|
-- Include
|
|
require( 'EgtPoint3d')
|
|
--EnableDebug( false)
|
|
|
|
|
|
-- Definizione classe BBox3d
|
|
BBox3d = {{},{}}
|
|
BBox3d.__index = BBox3d
|
|
|
|
-- funzione di utilita' per identificazione tipo
|
|
function isBBox3d( a)
|
|
return ( getmetatable( a) == BBox3d)
|
|
end
|
|
|
|
local function New( a, b)
|
|
local b3d = setmetatable( {{GEO.INFINITO,GEO.INFINITO,GEO.INFINITO},{-GEO.INFINITO,-GEO.INFINITO,-GEO.INFINITO}}, BBox3d)
|
|
if not a then
|
|
b3d[1] = Point3d( GEO.INFINITO, GEO.INFINITO, GEO.INFINITO)
|
|
b3d[2] = Point3d( -GEO.INFINITO, -GEO.INFINITO, -GEO.INFINITO)
|
|
elseif isBBox3d( a) then
|
|
b3d[1] = Point3d( a[1])
|
|
b3d[2] = Point3d( a[2])
|
|
elseif isBBox3d( a) and isBBox3d( b) then
|
|
b3d[1] = Point3d( a[1])
|
|
b3d[2] = Point3d( a[2])
|
|
BBox3d.AddPoint( b3d, b[1])
|
|
BBox3d.AddPoint( b3d, b[2])
|
|
elseif type(a) == 'table' and #a >= 2 and
|
|
type(a[1]) == 'table' and #a[1] >= 3 and
|
|
type(a[2]) == 'table' and #a[2] >= 3 then
|
|
b3d[1] = Point3d( GEO.INFINITO, GEO.INFINITO, GEO.INFINITO)
|
|
b3d[2] = Point3d( -GEO.INFINITO, -GEO.INFINITO, -GEO.INFINITO)
|
|
if a[1][1] < ( a[2][1] + GEO.EPS_SMALL) and
|
|
a[1][2] < ( a[2][2] + GEO.EPS_SMALL) and
|
|
a[1][3] < ( a[2][3] + GEO.EPS_SMALL) then
|
|
BBox3d.AddPoint( b3d, a[1])
|
|
BBox3d.AddPoint( b3d, a[2])
|
|
end
|
|
elseif isPoint3d( a) and isPoint3d( b) then
|
|
b3d[1] = Point3d(GEO.INFINITO,GEO.INFINITO,GEO.INFINITO)
|
|
b3d[2] = Point3d(-GEO.INFINITO,-GEO.INFINITO,-GEO.INFINITO)
|
|
BBox3d.AddPoint( b3d, a)
|
|
BBox3d.AddPoint( b3d, b)
|
|
elseif isPoint3d( a) then
|
|
b3d[1] = Point3d(GEO.INFINITO,GEO.INFINITO,GEO.INFINITO)
|
|
b3d[2] = Point3d(-GEO.INFINITO,-GEO.INFINITO,-GEO.INFINITO)
|
|
BBox3d.AddPoint( b3d, a)
|
|
else
|
|
error( 'A parameter is wrong', 2)
|
|
end
|
|
return b3d
|
|
end
|
|
|
|
setmetatable( BBox3d, { __call = function( _, ...) return New( ...) end })
|
|
|
|
-- verifico se vuoto
|
|
function BBox3d:isEmpty()
|
|
-- il minimo non è minore del massimo
|
|
return not ( self[1][1] < ( self[2][1] + GEO.EPS_SMALL) and
|
|
self[1][2] < ( self[2][2] + GEO.EPS_SMALL) and
|
|
self[1][3] < ( self[2][3] + GEO.EPS_SMALL) )
|
|
end
|
|
|
|
-- somma di due box (+)
|
|
function BBox3d.__add( a, b)
|
|
if isBBox3d( a) and isBBox3d( b) then
|
|
return New( a, b)
|
|
else
|
|
error( 'A parameter is not a BBox3d', 2)
|
|
end
|
|
end
|
|
|
|
-- aggiungo box o punto
|
|
function BBox3d:Add( a)
|
|
if isBBox3d( a) then
|
|
if not a:isEmpty() then
|
|
self:AddPoint( a[1])
|
|
self:AddPoint( a[2])
|
|
end
|
|
else
|
|
self:AddPoint( a)
|
|
end
|
|
end
|
|
|
|
-- aggiungo un punto (solo per uso interno)
|
|
function BBox3d:AddPoint( ptP)
|
|
if ptP[1] < self[1][1] then
|
|
self[1][1] = ptP[1]
|
|
end
|
|
if ptP[2] < self[1][2] then
|
|
self[1][2] = ptP[2]
|
|
end
|
|
if ptP[3] < self[1][3] then
|
|
self[1][3] = ptP[3]
|
|
end
|
|
if ptP[1] > self[2][1] then
|
|
self[2][1] = ptP[1]
|
|
end
|
|
if ptP[2] > self[2][2] then
|
|
self[2][2] = ptP[2]
|
|
end
|
|
if ptP[3] > self[2][3] then
|
|
self[2][3] = ptP[3]
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- espansione isotropa
|
|
function BBox3d:expand( dDelta)
|
|
if not isBBox3d( self) then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty(self) then
|
|
return true
|
|
end
|
|
self[1][1] = self[1][1] - dDelta
|
|
self[1][2] = self[1][2] - dDelta
|
|
self[1][3] = self[1][3] - dDelta
|
|
self[2][1] = self[2][1] + dDelta
|
|
self[2][2] = self[2][2] + dDelta
|
|
self[2][3] = self[2][3] + dDelta
|
|
end
|
|
|
|
-- traslazione
|
|
function BBox3d:move( m)
|
|
if not isBBox3d( self) then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty(self) then
|
|
return true
|
|
end
|
|
if isVector3d( m) or ( type( m) == 'table' and #m >= 3) then
|
|
self[1][1] = self[1][1] + m[1]
|
|
self[1][2] = self[1][2] + m[2]
|
|
self[1][3] = self[1][3] + m[3]
|
|
self[2][1] = self[2][1] + m[1]
|
|
self[2][2] = self[2][2] + m[2]
|
|
self[2][3] = self[2][3] + m[3]
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function BBox3d:rotate( ptAx, vtAx, dAngDeg)
|
|
if not isBBox3d( self) or not isPoint3d( ptAx) or not isVector3d( vtAx) or type( dAngDeg) ~= 'number' then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty(self) then
|
|
return true
|
|
end
|
|
local bOk, b3New = EgtBBoxRotate( self, ptAx, vtAx, dAngDeg)
|
|
if bOk then
|
|
self[1] = Point3d( b3New[1])
|
|
self[2] = Point3d( b3New[2])
|
|
end
|
|
return bOk
|
|
end
|
|
|
|
-- trasformazione di riferimento verso globale
|
|
function BBox3d:toGlob( fTool)
|
|
if not isBBox3d( self) or not isFrame3d( fTool) then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty(self) then
|
|
return true
|
|
end
|
|
local bOk, b3New = EgtBBoxToGlob( self, fTool)
|
|
if bOk then
|
|
self[1] = Point3d( b3New[1])
|
|
self[2] = Point3d( b3New[2])
|
|
end
|
|
return bOk
|
|
end
|
|
|
|
-- trasformazione di riferimento verso locale
|
|
function BBox3d:toLoc( fTool)
|
|
if not isBBox3d( self) or not isFrame3d( fTool) then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty(self) then
|
|
return true
|
|
end
|
|
local bOk, b3New = EgtBBoxToLoc( self, fTool)
|
|
if bOk then
|
|
self[1] = Point3d( b3New[1])
|
|
self[2] = Point3d( b3New[2])
|
|
end
|
|
return bOk
|
|
end
|
|
|
|
-- trasformazione di riferimento da locale a locale
|
|
function BBox3d:locToLoc( fOri, fDest)
|
|
if not isBBox3d( self) or not isFrame3d( fOri) or not isFrame3d( fDest) then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty(self) then
|
|
return true
|
|
end
|
|
local bOk, b3New = EgtBBoxLocToLoc( self, fOri, fDest)
|
|
if bOk then
|
|
self[1] = Point3d( b3New[1])
|
|
self[2] = Point3d( b3New[2])
|
|
end
|
|
return bOk
|
|
end
|
|
|
|
-- restituzione componenti
|
|
function BBox3d:getMin()
|
|
if BBox3d.isEmpty(self) then
|
|
return nil
|
|
end
|
|
return Point3d( self[1])
|
|
end
|
|
|
|
function BBox3d:getMax()
|
|
if BBox3d.isEmpty(self) then
|
|
return nil
|
|
end
|
|
return Point3d( self[2])
|
|
end
|
|
|
|
function BBox3d:getDimX()
|
|
if BBox3d.isEmpty(self) then
|
|
return nil
|
|
end
|
|
return ( self[2][1] - self[1][1])
|
|
end
|
|
|
|
function BBox3d:getDimY()
|
|
if BBox3d.isEmpty(self) then
|
|
return nil
|
|
end
|
|
return ( self[2][2] - self[1][2])
|
|
end
|
|
|
|
function BBox3d:getDimZ()
|
|
if BBox3d.isEmpty(self) then
|
|
return nil
|
|
end
|
|
return ( self[2][3] - self[1][3])
|
|
end
|
|
|
|
function BBox3d:getCenter()
|
|
if BBox3d.isEmpty(self) then
|
|
return nil
|
|
end
|
|
return 0.5 * ( Point3d( self[1]) + Point3d( self[2]))
|
|
end
|
|
|
|
function BBox3d:getRadius()
|
|
if BBox3d.isEmpty(self) then
|
|
return nil
|
|
end
|
|
return 0.5 * dist( Point3d( self[1]), Point3d( self[2]))
|
|
end
|
|
|
|
-- conversione in stringa (tostring)
|
|
function BBox3d:__tostring()
|
|
if BBox3d.isEmpty(self) then
|
|
return '(empty)'
|
|
end
|
|
return '('.. tostring(self[1])..','..tostring(self[2])..')'
|
|
end
|
|
|
|
-- verifica che il box includa il punto in XY
|
|
function EnclosesPointXY( b3Box, ptP)
|
|
if b3Box[2][1] < ptP[1] - GEO.EPS_SMALL or b3Box[1][1] > ptP[1] + GEO.EPS_SMALL then
|
|
return false
|
|
end
|
|
if b3Box[2][2] < ptP[2] - GEO.EPS_SMALL or b3Box[1][2] > ptP[2] + GEO.EPS_SMALL then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- verifica che il primo box includa il secondo in XY
|
|
function EnclosesXY( b3First, b3Second)
|
|
if not isBBox3d( b3First) or not isBBox3d( b3Second) then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty( b3First) or BBox3d.isEmpty( b3Second) then
|
|
return false
|
|
end
|
|
return EnclosesPointXY( b3First, b3Second:getMin()) and EnclosesPointXY( b3First, b3Second:getMax())
|
|
end
|
|
|
|
-- verifica di interferenza tra due box in XY
|
|
function OverlapsXY( b3First, b3Second)
|
|
if not isBBox3d( b3First) or not isBBox3d( b3Second) then
|
|
return false
|
|
end
|
|
if BBox3d.isEmpty( b3First) or BBox3d.isEmpty( b3Second) then
|
|
return false
|
|
end
|
|
if b3First[2][1] < b3Second[1][1] - GEO.EPS_SMALL or b3First[1][1] > b3Second[2][1] + GEO.EPS_SMALL then
|
|
return false
|
|
end
|
|
if b3First[2][2] < b3Second[1][2] - GEO.EPS_SMALL or b3First[1][2] > b3Second[2][2] + GEO.EPS_SMALL then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
|
|
return EgtBBox3d
|