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: