-- 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