mirror of
https://codeberg.org/1414codeforge/gear.git
synced 2025-06-05 22:09:24 +02:00
[spec/*,*] Split library in submodules.
This commit is contained in:
135
rect.lua
Normal file
135
rect.lua
Normal file
@ -0,0 +1,135 @@
|
||||
--- Axis-aligned rectangles.
|
||||
--
|
||||
-- Function for basic bounding rectangles building and testing.
|
||||
--
|
||||
-- @module gear.rect
|
||||
-- @copyright 2022 The DoubleFourteen Code Forge
|
||||
-- @author Lorenzo Cogotti
|
||||
|
||||
local rotatesincos = require((...):gsub('rect', '')..'vec').rotatesincos
|
||||
|
||||
local min, max = math.min, math.max
|
||||
local abs = math.abs
|
||||
|
||||
local rect = {}
|
||||
|
||||
|
||||
--- Extend rectangle to include a point.
|
||||
function rect.expand(x,y,w,h, px,py)
|
||||
if w < 0 or h < 0 then
|
||||
return px,py,0,0
|
||||
end
|
||||
|
||||
local xw, yh
|
||||
x = min(x, px)
|
||||
y = min(y, py)
|
||||
xw = max(x+w, px)
|
||||
yh = max(y+h, py)
|
||||
|
||||
return x, y, xw-x, yh-y
|
||||
end
|
||||
|
||||
--- Calculate and return the union of two rectangles.
|
||||
function rect.union(x1,y1,w1,h1, x2,y2,w2,h2)
|
||||
local xw1,yh1, xw2,yh2
|
||||
|
||||
if w1 < 0 or h1 < 0 then
|
||||
local huge = math.huge
|
||||
|
||||
x1,y1,xw1,yh1 = huge,huge,-huge,-huge
|
||||
else
|
||||
xw1,yh1 = x1 + w1,y1 + h1
|
||||
end
|
||||
if w2 < 0 or h2 < 0 then
|
||||
local huge = math.huge
|
||||
|
||||
x2,y2,xw2,yh2 = huge,huge,-huge,-huge
|
||||
else
|
||||
xw2,yh2 = x2 + w2,y2 + h2
|
||||
end
|
||||
|
||||
x1 = min(x1, x2)
|
||||
y1 = min(y1, y2)
|
||||
xw1 = max(xw1, xw2)
|
||||
xh1 = max(xh1, xh2)
|
||||
|
||||
return x1, y1, xw1 - x1, yh1 - y1
|
||||
end
|
||||
|
||||
--- Calculate and return the intersection between two rectangles.
|
||||
function rect.intersection(x1,y1,w1,h1, x2,y2,w2,h2)
|
||||
if w1 < 0 or h1 < 0 then
|
||||
return x1,y1,w1,h1
|
||||
elseif w2 < 0 or h2 < 0 then
|
||||
return x2,y2,w2,h2
|
||||
end
|
||||
|
||||
local xw1,yh1 = x1+w1, y1+h1
|
||||
local xw2,yh2 = x2+w2, y2+h2
|
||||
|
||||
x1 = max(x1, x2)
|
||||
y1 = max(y1, y2)
|
||||
xw1 = min(xw1, xw2)
|
||||
yh1 = min(yh1, yh2)
|
||||
return x1,y1, xw1-x1,yh1-y1
|
||||
end
|
||||
|
||||
--- Rotate rectangle around (ox,oy) about rot radians,
|
||||
-- and return the result's minimum enclosing
|
||||
-- axis-aligned rectangle.
|
||||
--
|
||||
-- NOTE: This causes precision loss, possibly generating
|
||||
-- larger bounds than needed for the rotated geometry
|
||||
-- Don't use this function repeatedly on the same bounds.
|
||||
function rect.rotate(rx,ry,rw,rh, rot, ox,oy)
|
||||
if rw < 0 or rh < 0 then
|
||||
return rx,ry,rw,rh
|
||||
end
|
||||
|
||||
ox = ox or 0
|
||||
oy = oy or 0
|
||||
|
||||
local sina,cosa = sin(rot),cos(rot)
|
||||
|
||||
local x1,y1 = rotatesincos(rx, ry, sina,cosa, ox,oy)
|
||||
local x2,y2 = rotatesincos(rx+rw, ry, sina,cosa, ox,oy)
|
||||
local x3,y3 = rotatesincos(rx+rw, ry+rh, sina,cosa, ox,oy)
|
||||
local x4,y4 = rotatesincos(rx, ry+rh, sina,cosa, ox,oy)
|
||||
|
||||
local rxw, rxh
|
||||
rx = min(min(min(x1, x2), x3), x4)
|
||||
ry = min(min(min(y1, y2), y3), y4)
|
||||
rxw = max(max(max(x1, x2), x3), x4)
|
||||
ryh = max(max(max(y1, y2), y3), y4)
|
||||
|
||||
return rx,ry, rxw-rx,ryh-ry
|
||||
end
|
||||
|
||||
--- Test whether point (x,y) lies inside a rectangle.
|
||||
function rect.pointinside(x,y, rx,ry,rw,rh)
|
||||
return x >= rx and y >= ry and x-rx <= rw and y-ry <= rh
|
||||
end
|
||||
|
||||
--- Test whether the first rectangle lies inside the second.
|
||||
function rect.rectinside(x1,y1,w1,h1, x2,y2,w2,h2)
|
||||
return (x1 >= x2 and y1 >= y2 and w1 <= w2 and h1 <= h2 and w2 >= 0 and h2 >= 0)
|
||||
or ((w1 < 0 or h1 < 0) and (w2 >= 0 and h2 >= 0))
|
||||
end
|
||||
|
||||
--- Test two rectangles for equality with optional epsilon.
|
||||
function rect.eq(x1,y1,w1,h1, x2,y2,w2,h2, eps)
|
||||
eps = eps or 0.007
|
||||
|
||||
return (abs(x1 - x2) <= eps and
|
||||
abs(y1 - y2) <= eps and
|
||||
abs(w1 - w2) <= eps and
|
||||
abs(h1 - h2) <= eps)
|
||||
or ((w1 < 0 or h1 < 0) and (w2 < 0 or h2 < 0))
|
||||
end
|
||||
|
||||
--- Test whether a rectangle is empty.
|
||||
function rect.isempty(x,y,w,h)
|
||||
return w < 0 or h < 0
|
||||
end
|
||||
|
||||
return rect
|
Reference in New Issue
Block a user