doc: geometry module

pull/2416/head
Qingping Hou 8 years ago
parent 93e075feb6
commit 8799b4b6b1

@ -309,7 +309,7 @@ function ReaderFooter:addToMainMenu(tab_item_table)
y = DTAP_ZONE_MINIBAR.y, y = DTAP_ZONE_MINIBAR.y,
w = DTAP_ZONE_MINIBAR.w, w = DTAP_ZONE_MINIBAR.w,
h = DTAP_ZONE_MINIBAR.h h = DTAP_ZONE_MINIBAR.h
}:sizeof() == 0 then }:area() == 0 then
table.insert(sub_items, { table.insert(sub_items, {
text = _("Toggle mode"), text = _("Toggle mode"),
enabled_func = function() enabled_func = function()

@ -1,22 +1,34 @@
local Math = require("optmath") --[[--
local DEBUG = require("dbg")
--[[
2D Geometry utilities 2D Geometry utilities
all of these apply to full rectangles { x = ..., y = ..., w = ..., h = ... } All of these apply to full rectangles:
local Geom = require("ui/geometry")
Geom:new{ x = 1, y = 0, w = 100, h = 200, }
Some behaviour is defined for points:
Geom:new{ x = 0, y = 0, }
Some behaviour is defined for dimensions:
some behaviour is defined for points { x = ..., y = ... } Geom:new{ w = 600, h = 800, }
some behaviour is defined for dimensions { w = ..., h = ... }
just use it on simple tables that have x, y and/or w, h Just use it on simple tables that have x, y and/or w, h
or define your own types using this as a metatable or define your own types using this as a metatable
]]--
]]
local Math = require("optmath")
--[[--
@table Geom
]]
local Geom = { local Geom = {
x = 0, x = 0,
y = 0, y = 0,
w = 0, w = 0,
h = 0 h = 0,
} }
function Geom:new(o) function Geom:new(o)
@ -26,6 +38,10 @@ function Geom:new(o)
return o return o
end end
--[[--
Make a deep copy of itself.
@treturn Geom
]]
function Geom:copy() function Geom:copy()
local n = Geom:new() local n = Geom:new()
n.x = self.x n.x = self.x
@ -39,48 +55,60 @@ function Geom:__tostring()
return self.w.."x"..self.h.."+"..self.x.."+"..self.y return self.w.."x"..self.h.."+"..self.x.."+"..self.y
end end
--[[ --[[--
offset rectangle or point by relative values Offset rectangle or point by relative values
]]-- @int dx x delta
@int dy y delta
]]
function Geom:offsetBy(dx, dy) function Geom:offsetBy(dx, dy)
self.x = self.x + dx self.x = self.x + dx
self.y = self.y + dy self.y = self.y + dy
return self return self
end end
--[[ --[[--
offset rectangle or point to certain coordinates Offsets rectangle or point to certain coordinates
]]-- @int x new x
@int y new y
]]
function Geom:offsetTo(x, y) function Geom:offsetTo(x, y)
self.x = x self.x = x
self.y = y self.y = y
return self return self
end end
--[[ --[[--
scale rectangle (grow to bottom and to the right) or dimension Scales rectangle (grow to bottom and to the right) or dimension
if a single factor is given, it is applied to both width and height If a single factor is given, it is applied to both width and height
]]--
@int zx scale for x axis
@int zy scale for y axis
]]
function Geom:scaleBy(zx, zy) function Geom:scaleBy(zx, zy)
self.w = Math.round(self.w * zx) self.w = Math.round(self.w * zx)
self.h = Math.round(self.h * (zy or zx)) self.h = Math.round(self.h * (zy or zx))
return self return self
end end
--[[ --[[--
this method also takes care of x and y This method also takes care of x and y on top of @{Geom:scaleBy}
]]--
@int zx scale for x axis
@int zy scale for y axis
]]
function Geom:transformByScale(zx, zy) function Geom:transformByScale(zx, zy)
self.x = Math.round(self.x * zx) self.x = Math.round(self.x * zx)
self.y = Math.round(self.y * (zx or zy)) self.y = Math.round(self.y * (zx or zy))
self:scaleBy(zx, zy) self:scaleBy(zx, zy)
end end
--[[ --[[--
return size of geom Returns area of itself.
]]--
function Geom:sizeof() @treturn int
]]
function Geom:area()
if not self.w or not self.h then if not self.w or not self.h then
return 0 return 0
else else
@ -88,25 +116,31 @@ function Geom:sizeof()
end end
end end
--[[ --[[--
enlarges or shrinks dimensions or rectangles Enlarges or shrinks dimensions or rectangles
note that for rectangles the offset stays the same Note that for rectangles the offset stays the same
]]--
@int dw width delta
@int dh height delta
]]
function Geom:changeSizeBy(dw, dh) function Geom:changeSizeBy(dw, dh)
self.w = self.w + dw self.w = self.w + dw
self.h = self.h + dh self.h = self.h + dh
return self return self
end end
--[[ --[[--
return the outer rectangle that contains both us and a given rectangle Returns a new outer rectangle that contains both us and a given rectangle
works for rectangles, dimensions and points Works for rectangles, dimensions and points
]]--
@tparam Geom rect_b
@treturn Geom
]]
function Geom:combine(rect_b) function Geom:combine(rect_b)
local combined = self:copy() local combined = self:copy()
if not rect_b or rect_b:sizeof() == 0 then return combined end if not rect_b or rect_b:area() == 0 then return combined end
if combined.x > rect_b.x then if combined.x > rect_b.x then
combined.x = rect_b.x combined.x = rect_b.x
end end
@ -126,11 +160,13 @@ function Geom:combine(rect_b)
return combined return combined
end end
--[[ --[[--
returns a rectangle for the part that we and a given rectangle share Returns a new rectangle for the part that we and a given rectangle share
TODO: what happens if there is no rectangle shared? currently behaviour is undefined. @tparam Geom rect_b
@treturn Geom
]]-- ]]--
-- TODO: what happens if there is no rectangle shared? currently behaviour is undefined.
function Geom:intersect(rect_b) function Geom:intersect(rect_b)
-- make a copy of self -- make a copy of self
local intersected = self:copy() local intersected = self:copy()
@ -153,9 +189,11 @@ function Geom:intersect(rect_b)
return intersected return intersected
end end
--[[ --[[--
return true if self does not share any area with rect_b Return true if self does not share any area with rect_b
]]--
@tparam Geom rect_b
]]
function Geom:notIntersectWith(rect_b) function Geom:notIntersectWith(rect_b)
if (self.x >= (rect_b.x + rect_b.w)) if (self.x >= (rect_b.x + rect_b.w))
or (self.y >= (rect_b.y + rect_b.h)) or (self.y >= (rect_b.y + rect_b.h))
@ -166,28 +204,33 @@ function Geom:notIntersectWith(rect_b)
return false return false
end end
--[[ --[[--
return true if self geom shares area with rect_b Return true if self geom shares area with rect_b
]]--
@tparam Geom rect_b
]]
function Geom:intersectWith(rect_b) function Geom:intersectWith(rect_b)
return not self:notIntersectWith(rect_b) return not self:notIntersectWith(rect_b)
end end
--[[ --[[--
set size of dimension or rectangle to size of given dimension/rectangle Set size of dimension or rectangle to size of given dimension/rectangle
]]--
@tparam Geom rect_b
]]
function Geom:setSizeTo(rect_b) function Geom:setSizeTo(rect_b)
self.w = rect_b.w self.w = rect_b.w
self.h = rect_b.h self.h = rect_b.h
return self return self
end end
--[[ --[[--
check whether rect_b is within current rectangle Check whether rect_b is within current rectangle
works for dimensions, too Works for dimensions, too. For points, it is basically an equality check
for points, it is basically an equality check
]]-- @tparam Geom rect_b
]]
function Geom:contains(rect_b) function Geom:contains(rect_b)
if self.x <= rect_b.x if self.x <= rect_b.x
and self.y <= rect_b.y and self.y <= rect_b.y
@ -199,11 +242,13 @@ function Geom:contains(rect_b)
return false return false
end end
--[[ --[[--
check for equality Check for equality
works for rectangles, points, dimensions Works for rectangles, points, dimensions
]]--
@tparam Geom rect_b
]]
function Geom:__eq(rect_b) function Geom:__eq(rect_b)
if self.x == rect_b.x if self.x == rect_b.x
and self.y == rect_b.y and self.y == rect_b.y
@ -214,9 +259,11 @@ function Geom:__eq(rect_b)
return false return false
end end
--[[ --[[--
check size of dimension/rectangle for equality Check size of dimension/rectangle for equality
]]--
@tparam Geom rect_b
]]
function Geom:equalSize(rect_b) function Geom:equalSize(rect_b)
if self.w == rect_b.w if self.w == rect_b.w
and self.h == rect_b.h and self.h == rect_b.h
@ -226,9 +273,11 @@ function Geom:equalSize(rect_b)
return false return false
end end
--[[ --[[--
check if our size is smaller than the size of the given dimension/rectangle Check if our size is smaller than the size of the given dimension/rectangle
]]--
@tparam Geom rect_b
]]
function Geom:__lt(rect_b) function Geom:__lt(rect_b)
DEBUG("lt:",self,rect_b) DEBUG("lt:",self,rect_b)
if self.w < rect_b.w and self.h < rect_b.h then if self.w < rect_b.w and self.h < rect_b.h then
@ -239,9 +288,10 @@ DEBUG("lt-")
return false return false
end end
--[[ --[[--
check if our size is smaller or equal the size of the given dimension/rectangle Check if our size is smaller or equal the size of the given dimension/rectangle
]]-- @tparam Geom rect_b
]]
function Geom:__le(rect_b) function Geom:__le(rect_b)
if self.w <= rect_b.w and self.h <= rect_b.h then if self.w <= rect_b.w and self.h <= rect_b.h then
return true return true
@ -249,13 +299,17 @@ function Geom:__le(rect_b)
return false return false
end end
--[[ --[[--
offset the current rectangle by dx, dy while fitting it into the space Offset the current rectangle by dx, dy while fitting it into the space
of a given rectangle of a given rectangle
this can also be called with dx=0 and dy=0, which will fit the current This can also be called with dx=0 and dy=0, which will fit the current
rectangle into the given rectangle rectangle into the given rectangle
]]--
@tparam Geom rect_b
@int dx
@int dy
]]
function Geom:offsetWithin(rect_b, dx, dy) function Geom:offsetWithin(rect_b, dx, dy)
-- check size constraints and shrink us when we're too big -- check size constraints and shrink us when we're too big
if self.w > rect_b.w then if self.w > rect_b.w then
@ -282,9 +336,13 @@ function Geom:offsetWithin(rect_b, dx, dy)
end end
end end
--[[ --[[--
center the current rectangle at position x and y of a given rectangle Center the current rectangle at position x and y of a given rectangle
]]--
@tparam Geom rect_b
@int dx
@int dy
]]
function Geom:centerWithin(rect_b, x, y) function Geom:centerWithin(rect_b, x, y)
-- check size constraints and shrink us when we're too big -- check size constraints and shrink us when we're too big
if self.w > rect_b.w then if self.w > rect_b.w then
@ -316,16 +374,21 @@ function Geom:shrinkInside(rect_b, dx, dy)
return self:intersect(rect_b) return self:intersect(rect_b)
end end
--[[ --[[--
return the Euclidean distance between two geoms Return the Euclidean distance between two geoms
]]--
@tparam Geom rect_b
]]
function Geom:distance(geom) function Geom:distance(geom)
return math.sqrt(math.pow(self.x - geom.x, 2) + math.pow(self.y - geom.y, 2)) return math.sqrt(math.pow(self.x - geom.x, 2) + math.pow(self.y - geom.y, 2))
end end
--[[ --[[--
return the midpoint of two geoms Return the midpoint of two geoms
]]--
@tparam Geom geom
@treturn Geom
]]
function Geom:midpoint(geom) function Geom:midpoint(geom)
return Geom:new{ return Geom:new{
x = Math.round((self.x + geom.x) / 2), x = Math.round((self.x + geom.x) / 2),
@ -334,9 +397,10 @@ function Geom:midpoint(geom)
} }
end end
--[[ --[[--
return center point in this geom Return center point in this geom
]]-- @treturn Geom
]]
function Geom:center() function Geom:center()
return Geom:new{ return Geom:new{
x = self.x + Math.round(self.w / 2), x = self.x + Math.round(self.w / 2),

Loading…
Cancel
Save