lua optimize poly_draw add draw_number, poly_points modules

Change-Id: Id36e765f18234f5a4f3092d090c0adffa3da1612
This commit is contained in:
William Wilgus 2019-08-26 22:17:33 -05:00
parent 9f551b09f6
commit b99d4d7fa9
4 changed files with 297 additions and 43 deletions

View file

@ -0,0 +1,115 @@
--[[ Lua draw number function
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2019 William Wilgus
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
]]
--[[ Exposed Functions
_draw_nums.print; binary (base = 2) , octal (base = 8), hexadecimal (base = 16)
_draw_nums.nums; table of number characters
]]
if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
local _draw_nums = {} do
local _poly = require "draw_poly"
-- every 2 elements is an x, y coord pair
-- n[?] = {x,y,x,y,x,y}
local nums = {
["b"] = {0,1,0,7,0,5,1,4,1,4,2,4,3,5,3,6,2,7,1,7,0,6,0,5},
["o"] = {1,4,0,5,0,6,1,7,2,7,3,6,3,5,2,4,1,4},
["x"] = {0,3,4,7,2,5,4,3,0,7},
[-1] = {1,4, 3,4},
[0] = {1,2,1,6,2,7,3,7,4,6,4,2,3,1,2,1,1,2},
[1] = {3,1,3,7},
[2] = {1,1,3,1,4,2,4,3,3,4,1,5,1,7,4,7},
[3] = {1,1,3,1,4,2,4,3,3,4,2,4,3,4,4,5,4,6,3,7,1,7},
[4] = {1,1,1,3,2,4,4,4,4,1,4,7},
[5] = {1,1,4,1,1,1,1,4,3,4,4,5,4,7,1,7},
[6] = {1,2,1,4,1,6,2,7,3,7,4,6,4,4,1,4,1,2,2,1,4,1},
[7] = {1,1,4,1,4,2,1,7},
[8] = {1,2,1,6,2,7,3,7,4,6,4,4,1,4,4,4,4,2,3,1,2,1,1,2},
[9] = {4,6,4,4,4,2,3,1,2,1,1,2,1,4,4,4,4,6,3,7,1,7},
[10] = {1,7,1,4,4,4,4,7,4,2,3,1,2,1,1,2,1,4},
[11] = {1,1,1,7,3,7,4,6,4,5,3,4,1,4,3,4,4,3,4,2,3,1,1,1},
[12] = {4,2,3,1,2,1,1,2,1,6,2,7,3,7,4,6},
[13] = {1,1,1,7,3,7,4,6,4,2,3,1,1,1},
[14] = {4,1,1,1,1,4,3,4,1,4,1,7,4,7},
[15] = {4,1,1,1,1,4,3,4,1,4,1,7},
}
_draw_nums.nums = nums
_draw_nums.print = function(img, num, x, y, chrw, color, base, prefix, bClip, scale_x, scale_y, t_nums)
scale_x = scale_x or 1
scale_y = scale_y or 1
chrw = chrw * scale_x
prefix = (prefix == nil or prefix == true) and true or false
t_nums = t_nums or nums
local max_x, max_y, digits = 0, 0, {}
if num <= 0 then
if num < 0 then
digits[-3] = -1
num = -num
else
digits[0] = 0
end
end
if not prefix and (base == 2 or base == 8 or base == 16) then
-- no prefix
elseif base == 2 then
digits[-1] = "b"
elseif base == 8 then
digits[-1] = "o"
elseif base == 10 then
-- no prefix
elseif base == 16 then
digits[-2] = 0
digits[-1] = "x"
elseif base == nil then -- default
base = 10
else
error("unknown number base: " .. base)
return nil
end
while num > 0 do -- get each digit (LeastSignificant)
digits[#digits + 1] = num % base;
num=num/base;
end
digits[#digits + 1] = digits[0] -- zero
digits[#digits + 1] = digits[-1] -- base prefix
digits[#digits + 1] = digits[-2] -- base prefix (hex)
digits[#digits + 1] = digits[-3] -- neg sign
for i = #digits, 1, -1 do
max_x, max_y = _poly.polyline(img, x, y, t_nums[digits[i]],
color, false, bClip, scale_x, scale_y)
x = x + chrw
end
return x, y + max_y, chrw
end
end
return _draw_nums

View file

@ -25,7 +25,11 @@
_poly.polygon
_poly.polyline
]]
--[[
every 2 elements in t_pts is an x, y coord pair
p[?] = {x,y,x,y,x,y}
lines get drawn between the coords
]]
if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
local _poly = {} do
@ -39,66 +43,83 @@ local _poly = {} do
local _copy = rocklib_image.copy
local _line = rocklib_image.line
local _newimg = rb.new_image
local flood_fill = require("draw_floodfill")
local flood_fill
-- draws a non-filled figure based on points in t-points
local function polyline(img, x, y, t_points, color, bClosed, bClip)
if #t_points < 2 then error("not enough points", 3) end
local function polyline(img, x, y, t_pts, color, bClosed, bClip, scale_x, scale_y)
scale_x = scale_x or 1
scale_y = scale_y or 1
local pt_first_last
local pt_first_last, pt1, pt2
local max_x, max_y = 0, 0
local len = #t_pts
if len < 4 then error("not enough points", 3) end
if bClosed then
pt_first_last = t_points[1]
pt_first_last = {t_pts[1] * scale_x, t_pts[2] * scale_y}
else
pt_first_last = t_points[#t_points]
pt_first_last = {t_pts[len - 1] * scale_x, t_pts[len] * scale_y}
end
for i = 1, #t_points, 1 do
local pt1 = t_points[i]
local pt2 = t_points[i + 1] or pt_first_last-- first and last point
pt2 = {t_pts[1] * scale_x, t_pts[2] * scale_y}
for i = 3, len + 2, 2 do
pt1 = pt2
if t_pts[i + 1] == nil then
pt2 = pt_first_last
else
pt2 = {t_pts[i] * scale_x, t_pts[i + 1] * scale_y}
end-- first and last point
_line(img, pt1[1] + x, pt1[2] + y, pt2[1] + x, pt2[2] + y, color, bClip)
if pt1[1] > max_x then max_x = pt1[1] end
if pt1[2] > max_y then max_y = pt1[2] end
end
if pt2[1] > max_x then max_x = pt2[1] end
if pt2[2] > max_y then max_y = pt2[2] end
return max_x + x, max_y + y
end
-- draws a closed figure based on points in t_points
_poly.polygon = function(img, x, y, t_points, color, fillcolor, bClip)
if #t_points < 2 then error("not enough points", 3) end
-- draws a closed figure based on points in t_pts
_poly.polygon = function(img, x, y, t_pts, color, fillcolor, bClip, scale_x, scale_y)
scale_x = scale_x or 1
scale_y = scale_y or 1
if #t_pts < 2 then error("not enough points", 3) end
if fillcolor then
local x_min, x_max = 0, 0
local y_min, y_max = 0, 0
local w, h = 0, 0
-- find boundries of polygon
for i = 1, #t_points, 1 do
local pt = t_points[i]
if pt[1] < x_min then x_min = pt[1] end
if pt[1] > x_max then x_max = pt[1] end
if pt[2] < y_min then y_min = pt[2] end
if pt[2] > y_max then y_max = pt[2] end
end
w = _abs(x_max) + _abs(x_min)
h = _abs(y_max) + _abs(y_min)
x_min = x_min - 2 -- leave a border to use flood_fill
y_min = y_min - 2
flood_fill = flood_fill or require("draw_floodfill")
local x_min, x_max = 0, 0
local y_min, y_max = 0, 0
local w, h = 0, 0
local pt1, pt2
-- find boundries of polygon
for i = 1, #t_pts, 2 do
if t_pts[i] < x_min then x_min = t_pts[i] end
if t_pts[i] > x_max then x_max = t_pts[i] end
local fill_img = _newimg(w + 3, h + 3)
_clear(fill_img, 0x1)
if t_pts[i+1] < y_min then y_min = t_pts[i+1] end
if t_pts[i+1] > y_max then y_max = t_pts[i+1] end
end
x_max = x_max * scale_x
x_min = x_min * scale_x
y_max = y_max * scale_y
y_min = y_min * scale_y
w = _abs(x_max) + _abs(x_min)
h = _abs(y_max) + _abs(y_min)
x_min = -(x_min - 2) -- leave a border to use flood_fill
y_min = -(y_min - 2)
for i = 1, #t_points, 1 do
local pt1 = t_points[i]
local pt2 = t_points[i + 1] or t_points[1]-- first and last point
_line(fill_img, pt1[1] - x_min, pt1[2] - y_min,
pt2[1]- x_min, pt2[2] - y_min, 0)
local fill_img = _newimg(w + 3, h + 3)
_clear(fill_img, 0x1)
end
polyline(fill_img, x_min, y_min, t_pts,
0x0, true, bClip, scale_x, scale_y)
-- flood the outside of the figure with 0 the inside will be fillcolor
flood_fill(fill_img, fill_img:width(), fill_img:height() , 0x1, 0x0)
_copy(img, fill_img, x - 1, y - 1, _NIL, _NIL, _NIL, _NIL, bClip, BSAND, fillcolor)
_copy(img, fill_img, x - 1, y - 1,
_NIL, _NIL, _NIL, _NIL, bClip, BSAND, fillcolor)
end
polyline(img, x, y, t_points, color, true, bClip)
polyline(img, x, y, t_pts, color, true, bClip, scale_x, scale_y)
end
-- expose internal functions to the outside through _poly table

View file

@ -0,0 +1,118 @@
--PolyPoints.lua
--[[
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2017 William Wilgus
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
]]
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- decodes ascii string back to t_pts
function points_from_ascii(encstr, scale)
scale = scale or 1
local t_pts = {}
encstr = encstr or "00000008"
local chroffset = tonumber(string.sub(encstr, 1, 3)) or 0
local chrlen = tonumber(string.sub(encstr, 4, 8)) or 0
if string.len(encstr) ~= chrlen then
error("Invalid Points String" .. string.len(encstr), 2)
end
for i = 9, string.len(encstr) - 1, 2 do
local x = string.byte(encstr, i, i) - chroffset
local y = string.byte(encstr, i + 1, i + 1) - chroffset
t_pts[#t_pts + 1] = x * scale
t_pts[#t_pts + 1] = y * scale
end
return t_pts
end
--------------------------------------------------------------------------------
-- encodes t_pts as a ascii string non print chars are excluded so
-- size is limited to approx ~ 90x90
function points_to_ascii(t_pts)
if not t_pts then return "" end
local chroffset = 33
local maxoffset = 126 - 33
local t_enc = {[1] = string.format("%03d%05d", chroffset, #t_pts + 8)}
local max_n, min_n = 0, 0
for i = 1, #t_pts, 2 do
if t_pts[i] > max_n then max_n = t_pts[i] end
if t_pts[i] < min_n then min_n = t_pts[i] end
if t_pts[i+1] > max_n then max_n = t_pts[i+1] end
if t_pts[i+1] < min_n then min_n = t_pts[i+1] end
if max_n > maxoffset or min_n < 0 then break; end
t_enc[#t_enc + 1] = string.char(t_pts[i] + chroffset)
t_enc[#t_enc + 1] = string.char(t_pts[i+1] + chroffset)
end
if min_n >= 0 and (max_n - min_n) <= maxoffset then
return table.concat(t_enc)
else
return "00000008"
end
end
--------------------------------------------------------------------------------
-- scales t_pts by percentage (x/y)
function points_scale_pct(t_pts, x_pct, y_pct)
for i = 1, #t_pts, 2 do
local t_pt = {t_pts[i], t_pts[i + 1]}
t_pt = t_pt or {0, 0}
t_pts[i] = (t_pt[1] * x_pct) / 100
t_pts[i+1] = (t_pt[2] * y_pct) / 100
end
return t_pts
end
--------------------------------------------------------------------------------
-- scales t_pts by (x/y)
function points_scale(t_pts, width, height)
local max_x, max_y = 0, 0
for i = 1, #t_pts, 2 do
if t_pts[i] > max_x then max_x = t_pts[i] end
if t_pts[i+1] > max_y then max_y = t_pts[i+1] end
end
local x_pct = (width * 100) / max_x
local y_pct = (height * 100) / max_y
return points_scale_pct(t_pts, x_pct, y_pct)
end
--------------------------------------------------------------------------------
--[[
function scaleup(t_pts, scale_x, scale_y)
local t_coord
for key,value in pairs(t_pts) do
t_coord = t_pts[key]
t_coord[1] = t_coord[1] * scale_x
t_coord[2] = t_coord[2] * scale_y
t_pts[key] = t_coord
end
end
function scaledn(t_pts, scale_x, scale_y)
local t_coord
for key,value in pairs(t_pts) do
t_coord = t_pts[key]
t_coord[1] = t_coord[1] / scale_x
t_coord[2] = t_coord[2] / scale_y
t_pts[key] = t_coord
end
end
]]

View file

@ -17,9 +17,9 @@ OTHER_SRC += $(LUA_SRC)
LUA_INCLUDEDIR := $(LUA_SRCDIR)/include_lua
LUA_INCLUDELIST := $(addprefix $(LUA_BUILDDIR)/,audio.lua blit.lua color.lua draw.lua draw_floodfill.lua draw_poly.lua \
draw_text.lua image.lua image_save.lua lcd.lua math_ex.lua print.lua \
timer.lua playlist.lua pcm.lua sound.lua \
rbcompat.lua printtable.lua)
draw_num.lua draw_text.lua image.lua image_save.lua lcd.lua math_ex.lua \
print.lua timer.lua playlist.lua pcm.lua sound.lua \
rbcompat.lua poly_points.lua printtable.lua)
ifndef APP_TYPE