|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- zrect.lua: the ZRect class for dednat6
-- This file:
-- http://angg.twu.net/dednat5/zrect.lua
-- http://angg.twu.net/dednat5/zrect.lua.html
-- (find-angg "dednat5/zrect.lua")
--
-- ZRects are read from ascii files as rectangles, and they can be
-- converted into many other things - for example, we can latex them
-- by converting them into Picture objects.
-- Older version: (find-angg "LUA/picture.lua" "Rectdef")
--
-- «.zrectdefs_get» (to "zrectdefs_get")
-- «.zrectdefs_get-tests» (to "zrectdefs_get-tests")
-- «.ZRect» (to "ZRect")
-- «.getrect» (to "getrect")
-- «.getrect-tests» (to "getrect-tests")
-- «.getrectdefs» (to "getrectdefs")
-- «.getrectdefs-tests» (to "getrectdefs-tests")
-- «.Rectdef» (to "Rectdef")
-- «.Rectdef-tests» (to "Rectdef-tests")
require "picture" -- (find-dn5 "picture.lua")
-- _ _ __
-- _____ __ ___ ___| |_ __| | ___ / _|___
-- |_ / '__/ _ \/ __| __/ _` |/ _ \ |_/ __|
-- / /| | | __/ (__| || (_| | __/ _\__ \
-- /___|_| \___|\___|\__\__,_|\___|_| |___/
--
-- «zrectdefs_get» (to ".zrectdefs_get")
--
-- We use zrectdefs to define ZSets, ZDAGs, Zfunctions, etc, in 2D
-- ascii diagrams embedded in LaTeX comments in "%R" blocks.
-- See: (find-dn5 "heads6.lua" "zrect-head")
--
-- A "zrectdef" is 4-uple: (name, lop, rlines, rop).
-- In the test string below, the zrectdefs are:
-- ("a", "2", {" 00 ", ...}, ""),
-- ("b", "1", {"a b c ", ...}, "foo"),
-- ("c", "2", {" 23 ", ...}, "bar").
--
zrectdefs_bigstr_for_tests = [[
%R a := 2/ 00 \ b := 1/a b c \foo
%R |10 01| | d e f|
%R \ 00 / \ g /
%R
%R c := 2/ 23 \bar
%R | 22 13
%R | 12 03
%R | 11 02
%R |10 01
%R \ 00
%R
%R d := 2/ 54 \
%R |53 44
%R | 43 34
%R | 33
%R | 23
%R | 22 13
%R | 21 12
%R |20 11
%R | 10
%R \ 00
%R
]]
zrectdefs_get1 = function (lines, y1, p1, p2, name)
for y2=y1+1,#lines+1 do -- note: y2 == #lines+1
local c = (lines[y2] or ""):sub(p1-1, p1-1) -- implies c == ""
if c == "" then
error("Rectangle '"..name.." :=' at line "..y1..
" has no lower left '\\'")
elseif c == "\\" then
local rlines = {}
for y=y1,y2 do table.insert(rlines, lines[y]:sub(p1, p2-1)) end
return rlines
end
end
end
zrectdefs_get = function (lines, i, j, f)
f = f or zrectdef_f
for k=i,(j or i) do
local line = lines[k]
local pat = "(%w+) := ([^ /]*)/().-()\\([^ ]*)"
for name,lop,p1,p2,rop in line:gmatch(pat) do
local rlines = zrectdefs_get1(lines, k, p1, p2, name)
f(name, lop, rlines, rop)
end
end
end
-- What to do with each zrectdef
-- (i.e., good values for the "f" in for zrectdefs_get)
zrectdef_print = function (name, lop, rlines, rop)
print(name.." := "..lop.."(")
print(table.concat(rlines, "\n"))
print(")"..rop)
end
zrects = {}
zrectdef_store = function (name, lop, rlines, rop)
zrects[name] = ZRect.from(name, lop, rlines, rop):setlrdata() -- see below
end
zrectdef_f = zrectdef_store
-- «zrectdefs_get-tests» (to ".zrectdefs_get-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "zrect.lua"
lines = splitlines(untabify(zrectdefs_bigstr_for_tests))
zrectdefs_get(lines, 1, nil, PP)
zrectdef_f = PP
zrectdefs_get(lines, 5, nil)
zrectdefs_get(lines, 5, nil, zrectdef_print)
zrectdef_f = zrectdef_store
zrectdefs_get(lines, 1, 5)
= zrects.c
--]==]
-- _________ _ _
-- |__ / _ \ ___ ___| |_ ___| | __ _ ___ ___
-- / /| |_) / _ \/ __| __| / __| |/ _` / __/ __|
-- / /_| _ < __/ (__| |_ | (__| | (_| \__ \__ \
-- /____|_| \_\___|\___|\__| \___|_|\__,_|___/___/
--
-- «ZRect» (to ".ZRect")
-- ZRects are zrectdefs with extra information.
--
-- In a ZRect we can access the contents of each of its "cells" by its
-- coordinates, using several coordinate systems: row/col, X/y, x/y,
-- l/r. Several fields of a ZRect are variables (offsets, dimensions,
-- etc) that help in converting between those several coordinate
-- systems; other fields, like lop and rop, come from the zrectdef.
--
-- The easy conversions between coordinate systems are:
-- row/col <-> x/y <-> X/y <-> l/r
-- (row,col) := (nrows-y,x+1)
-- (col-1,nrows-row) =: (x,y)
-- (x,y) := (X+x0,y)
-- (x-x0,y) =: (X,y)
-- (X,y) := (r-l,r+l)
-- ((y-X)/2,(y+X)/2) =: (l,r)
--
ZRect = Class {
type = "ZRect",
from = function (name, lop, rlines, rop, w)
w = w or lop:sub(-1)+0 -- use the last digit of op when w==nil
return ZRect {
name = name,
lop = lop,
rop = rop,
w = w,
rlines = rlines,
nrows = #rlines,
ncols = #rlines[1] / w,
minx = 0, -- constant
miny = 0, -- constant
maxy = #rlines - 1,
maxx = (#rlines[1] / w) - 1,
}
end,
__tostring = function (zrect)
return zrect:toascii()
end,
__index = {
toascii0 = function (zrect) return table.concat(zrect.rlines, "\n") end,
toascii = function (zrect)
return format("%s = %s[[\n%s\n]]%s",
zrect.name, zrect.lop, zrect:toascii0(), zrect.rop)
end,
--
-- row/col coordinates
rcget0 = function (zrect, row, col)
local w = zrect.w
return zrect.rlines[row]:sub((col-1)*w+1, col*w)
end,
rcget = function (zrect, row, col)
if col < 1 then return end
return (zrect:rcget0(row, col):match("%S+"))
end,
--
-- calculate x0 (used to convert between x/y and X/y coordinates)
getx0 = function (zrect)
for x=0,zrect.maxx do
if zrect:xyget(x, 0) then return x end
end
end,
setx0 = function (zrect, x0)
x0 = x0 or zrect:getx0()
zrect.x0 = x0
zrect.minX = - x0
zrect.maxX = zrect.maxx - x0
return zrect
end,
--
xyget = function (zrect, x, y)
local row = zrect.nrows - y
local col = x + 1
return zrect:rcget(row, col)
end,
Xyget = function (zrect, X, y, verbose)
local x = X + zrect.x0
return zrect:xyget(x, y)
end,
--
-- l/r coordinates
Xytolr = function (zrect, X, y)
local l = (y - X) / 2
local r = (y + X) / 2
return l, r
end,
lrtoXy = function (zrect, l, r)
local X = r - l
local y = r + l
return X, y
end,
lrget = function (zrect, l, r)
return zrect:Xyget(zrect:lrtoXy(l, r))
end,
setlrdata0 = function (zrect)
local zr = zrect -- abbreviation
zr.minl, zr.minr = 0, 0 -- constants
zr.maxl, zr.maxr = 0, 0 -- modified below
zr.minlfor, zr.maxlfor = {}, {}
zr.minrfor, zr.maxrfor = {}, {}
for y=0,zrect.maxy do
for X=zrect.minX,zrect.maxX do
if zrect:Xyget(X, y) then
local l, r = zrect:Xytolr(X, y)
zr.maxl = Max(zr.maxl, l)
zr.maxr = Max(zr.maxr, r)
zr.minlfor[r] = Min(zr.minlfor[r], l)
zr.minrfor[l] = Min(zr.minrfor[l], r)
zr.maxlfor[r] = Max(zr.maxlfor[r], l)
zr.maxrfor[l] = Max(zr.maxrfor[l], r)
-- PP {X=X, y=y, A=zrect:Xyget(X, y), l=l, r=r}
end
end
end
return zr
end,
setlrdata = function (zrect)
return zrect:setx0():setlrdata0()
end,
--
-- Standard ways to convert a ZRect to a Picture object
topicture_xy0 = function (rd, opts, f)
f = f or function (x, y, s) return s end
local p = Picture.new(opts)
for y=rd.maxy,0,-1 do
for x=0,rd.maxx do
if rd:xyget(x, y) then
p:put(x, y, f(x, y, rd:xyget(x, y)))
end
end
end
return p
end,
topicture_Xy0 = function (rd, opts, f)
f = f or function (X, y, s) return s end
local p = Picture.new(opts)
for y=rd.maxy,0,-1 do
for X=rd.minX,rd.maxX do
if rd:Xyget(X, y) then
p:put(X, y, f(X, y, rd:Xyget(X, y)))
end
end
end
return p
end,
topicture_lr0 = function (rd, opts, f)
f = f or function (l, r, s) return s end
local p = Picture.new(opts)
for l=0,rd.maxl do
for r=0,rd.maxr do
if rd:lrget(l, r) then
p:lrput(l, r, f(l, r, rd:lrget(l, r)))
end
end
end
return p
end,
--
topicture = function (zrect, coordsys, opts, f)
local method = "topicture_"..coordsys.."0"
local p = zrect[method](zrect, opts, f)
return p
end,
--
-- Draw borders
drawline0 = function (zr, p, xy, dxdy, len)
local tex = format("\\put(%s){\\line(%s){%s}}\n", xy, dxdy, len)
table.insert(p.other, tex)
end,
drawborders = function (zr, p)
local l, r, oldl, oldr, delta
local setl = function (newl) oldl, delta, l = l, newl-l, newl end
local setr = function (newr) oldr, delta, r = r, newr-r, newr end
local maxl = function (r) return zr.maxlfor[r] end
local maxr = function (l) return zr.maxrfor[l] end
local minl = function (r) return zr.minlfor[r] end
local minr = function (l) return zr.minrfor[l] end
--
local south = function (l, r) return format("south(%d,%d)", l, r) end
local west = function (l, r) return format("west(%d,%d)", l, r) end
local east = function (l, r) return format("east(%d,%d)", l, r) end
local north = function (l, r) return format("north(%d,%d)", l, r) end
local nw, ne = "nw", "ne"
local pushline = function (...) PP(...) end
--
local nw, ne = "-1,1", "1,1"
local south = function (l, r) return {l=l-0.5, r=r-0.5} end
local west = function (l, r) return {l=l+0.5, r=r-0.5} end
local east = function (l, r) return {l=l-0.5, r=r+0.5} end
local north = function (l, r) return {l=l+0.5, r=r+0.5} end
local pushline = function (lr, dxdy, len)
p:lrputline(lr.l, lr.r, dxdy, len)
end
--
-- Left wall
l, r = 0, 0
setl(maxl(0)) -- move nw
pushline(south(0, 0), nw, delta+1)
while l < zr.maxl do
setr(minr(l+1)) -- move ne
pushline(west(l, oldr), ne, delta)
setl(maxl(r)) -- move nw
pushline(west(oldl, r), nw, delta)
end
setr(zr.maxr) -- move ne
pushline(west(l, oldr), ne, delta+1)
--
-- Right wall
l, r = 0, 0
setr(maxr(0)) -- move ne
pushline(south(0, 0), ne, delta+1)
while r < zr.maxr do
setl(minl(r+1)) -- move nw
pushline(east(oldl, r), nw, delta)
setr(maxr(l)) -- move ne
pushline(east(l, oldr), ne, delta)
end
setl(zr.maxl) -- move nw
pushline(east(oldl, r), nw, delta+1)
end,
drawcuts = function (zr, p, lcuts, rcuts)
local maxl = function (r) return zr.maxlfor[r] end
local maxr = function (l) return zr.maxrfor[l] end
local minl = function (r) return zr.minlfor[r] end
local minr = function (l) return zr.minrfor[l] end
--
local nw, ne = "-1,1", "1,1"
local south = function (l, r) return {l=l-0.5, r=r-0.5} end
local west = function (l, r) return {l=l+0.5, r=r-0.5} end
local east = function (l, r) return {l=l-0.5, r=r+0.5} end
local north = function (l, r) return {l=l+0.5, r=r+0.5} end
local pushline = function (lr, dxdy, len)
p:lrputline(lr.l, lr.r, dxdy, len)
end
--
for c in lcuts:gmatch"." do
local l = c+0
if l < zr.maxl then
local r1 = max(minr(l), minr(l+1))
local r2 = min(maxr(l), maxr(l+1))
pushline(west(l, r1), ne, r2-r1+1)
end
end
for c in rcuts:gmatch"." do
local r = c+0
if r < zr.maxr then
local l1 = max(minl(r), minl(r+1))
local l2 = min(maxl(r), maxl(r+1))
pushline(east(l1, r), nw, l2-l1+1)
end
end
end,
},
}
-- (find-es "lua5" "mult-as-comp")
-- «Rectdef-tests» (to ".Rectdef-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "zrect.lua"
lines = splitlines(untabify(zrectdefs_bigstr_for_tests))
zrectdefs_get(lines, 1, #lines, getrectdef_store)
PP(keys(zrects))
PP(zrects.c)
= zrects.c:toascii()
-- change to [[]]
rd = zrects.c
p = Picture {whats={}, scale="10pt"}
p = Picture {whats={}, scale="9pt"}
p = Picture {whats={}, scale="7pt", font="\\footnotesize "}
p = Picture.new {scale="10pt"}
p = Picture.new {scale="9pt"}
p = Picture.new {scale="7pt", font="\\footnotesize "}
for l=0,rd.maxl do
for r=0,rd.maxr do
if rd:lrget(l, r) then
-- PP(l, r, rd:lrget(l, r))
p:lrput(l, r, rd:lrget(l, r))
end
end
end
= p:toascii(" ")
= p:toascii("..")
= p:totex()
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "zrect.lua"
lines = splitlines(untabify(zrectdefs_bigstr_for_tests))
zrectdefs_get(lines, 1, #lines)
bu = function () return "$\\bullet$" end
ab = function (a, b) return format("$(%d,%d)$", a, b) end
rd = zrects.c
= rd:topicture_lr0 {scale="7pt", font="\\footnotesize "} :totex()
= rd:topicture_lr0({scale="4pt", font="\\footnotesize "}, bu):totex()
= rd:topicture_xy0({scale="4pt", font="\\footnotesize "}, ab):totex()
= rd:topicture_Xy0({scale="4pt", font="\\footnotesize "}, ab):totex()
= rd:toascii()
= rd:topicture_lr0( ):toascii(" ")
= rd:topicture_lr0( ):toascii("..")
= rd:topicture_lr0( ):totex()
= rd:topicture_lr0({} ):totex()
= rd:topicture_lr0({}, bu):totex()
= rd:topicture_xy0({}, ab):totex()
= rd:topicture_Xy0({}, ab):totex()
oc = {scale="12pt", font="\\footnotesize "}
o2 = {scale="7pt", font="\\footnotesize "}
ob = {scale="4pt", font="\\footnotesize "}
= rd:topicture_lr0(ob, bu):totex(),
rd:topicture_lr0(o2 ):totex(),
rd:topicture_lr0(oc, ab):totex(),
rd:topicture_xy0(oc, ab):totex(),
rd:topicture_Xy0(oc, ab):totex()
s = rd:topicture_lr0(ob, bu):lrput(0.5, 0, "$\\searrow$"):totex().."\n"..
rd:topicture_lr0(o2 ):totex().."\n"..
rd:topicture_lr0(oc, ab):totex().."\n"..
rd:topicture_xy0(oc, ab):totex().."\n"..
rd:topicture_Xy0(oc, ab):totex()
= s
writefile("/tmp/o.tex", s)
-- (find-fline "/tmp/o.tex")
-- (kill-new "$$\\input /tmp/o.tex $$")
-- (find-angg "LATEX/tmp.tex")
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "zrect.lua"
lines = splitlines(untabify(zrectdefs_bigstr_for_tests))
zrectdefs_get(lines, 1, #lines, getrectdef_store)
rd = zrects.c
d = function (e) PP(e, expr(e)) end
ds = function (es) for _,e in ipairs(split(es)) do d(e) end end
= rd:toascii()
ds "rd.minlfor rd.minrfor"
ds "rd.maxlfor rd.maxrfor"
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "zrect.lua"
lines = splitlines(untabify(zrectdefs_bigstr_for_tests))
zrectdefs_get(lines, 1, #lines)
rd = zrects.d
p = rd:topicture_lr0()
rd:drawborders(p)
= p:totex()
rd = zrects.d
p = rd:topicture_lr0()
rd:drawcuts(p, "01", "2345")
= p:totex()
-- Old stuff (broken)
PP(zrects.d)
PP(zrects.d.op)
PP(zrects.d.op:sub(-1))
PP(zrects.d.op:sub(-1) + 0)
zrects.d.w = 2
zrects.d.ncols = 5
zrects.d.nrows = 6
getcellatrowcol = function (rectdef, row, col)
local w = rectdef.w
return rectdef.lines[row]:sub((col-1)*w+1, col*w)
end
for row=1,zrects.d.nrows do
for col=1,zrects.d.ncols do
PP(row, col, getcellatrowcol(zrects.d, row, col))
end
end
--]==]
-- Local Variables:
-- coding: raw-text-unix
-- End: