Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://angg.twu.net/LUA/Pict2e1.lua.html -- http://angg.twu.net/LUA/Pict2e1.lua -- (find-angg "LUA/Pict2e1.lua") -- See: http://angg.twu.net/pict2e-lua.html -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- First version: 2022apr11 -- This version: 2022apr21 -- -- Pict2e1: generate code for Pict2e using -- Prads (printable algebraic datatypes). -- -- Based on: (find-angg "LUA/Prad1.lua") -- (find-LATEX "2022pict2e.lua") -- -- (defun a () (interactive) (find-angg "LUA/Pict2e1.lua")) -- (defun b () (interactive) (find-angg "LUA/Pict2e1-1.lua")) -- (defun ab () (interactive) (find-2b '(a) '(b))) -- (defun et () (interactive) (find-angg "LATEX/2022pict2e.tex")) -- (defun eb () (interactive) (find-angg "LATEX/2022pict2e-body.tex")) -- (defun ao () (interactive) (find-angg "LATEX/2022pict2e.lua")) -- (defun v () (interactive) (find-pdftools-page "~/LATEX/2022pict2e.pdf")) -- (defun tb () (interactive) (find-ebuffer (eepitch-target-buffer))) -- (defun etv () (interactive) (find-wset "13o2_o_o" '(tb) '(v))) -- (setenv "PICT2ELUADIR" "~/LATEX/") -- -- (code-c-d "pict2elua" "/tmp/pict2e-lua/" :anchor) -- (defun a () (interactive) (find-pict2elua "Pict2e1.lua")) -- (defun b () (interactive) (find-pict2elua "Pict2e1-1.lua")) -- (defun ab () (interactive) (find-2b '(a) '(b))) -- (defun et () (interactive) (find-pict2elua "2022pict2e.tex")) -- (defun eb () (interactive) (find-pict2elua "2022pict2e-body.tex")) -- (defun v () (interactive) (find-pdftools-page "/tmp/pict2e-lua/2022pict2e.pdf")) -- (defun tb () (interactive) (find-ebuffer (eepitch-target-buffer))) -- (defun etv () (interactive) (find-wset "13o2_o_o" '(tb) '(v))) -- (setenv "PICT2ELUADIR" "/tmp/pict2e-lua/") -- «.Prads» (to "Prads") -- «.PradOutput» (to "PradOutput") -- «.PradOutput-tests» (to "PradOutput-tests") -- «.PradContext» (to "PradContext") -- «.PradContext-tests» (to "PradContext-tests") -- «.PradStruct» (to "PradStruct") -- «.PradStruct-tests» (to "PradStruct-tests") -- «.PradClass» (to "PradClass") -- «.PradList» (to "PradList") -- «.PradSub» (to "PradSub") -- «.PradClass-tests» (to "PradClass-tests") -- -- «.nonPrads» (to "nonPrads") -- «.Show» (to "Show") -- «.Show-tests» (to "Show-tests") -- «.MiniV» (to "MiniV") -- «.MiniV-tests» (to "MiniV-tests") -- «.Points2» (to "Points2") -- «.Points2-tests» (to "Points2-tests") -- «.Pict2eVector» (to "Pict2eVector") -- «.Pict2eVector-tests» (to "Pict2eVector-tests") -- -- «.Pict2e» (to "Pict2e") -- «.PictList» (to "PictList") -- «.PictSub» (to "PictSub") -- «.Pict2e-tests» (to "Pict2e-tests") -- «.Pict2e-methods» (to "Pict2e-methods") -- «.Pict2e-methods-tests» (to "Pict2e-methods-tests") -- -- «.PictBounds» (to "PictBounds") -- «.PictBounds-tests» (to "PictBounds-tests") -- «.PictBounds-methods» (to "PictBounds-methods") -- «.PictBounds-methods-tests» (to "PictBounds-methods-tests") -- -- «.fake_ln_mod_x» (to "fake_ln_mod_x") require "edrxlib" -- ____ _ -- | _ \ _ __ __ _ __| |___ -- | |_) | '__/ _` |/ _` / __| -- | __/| | | (_| | (_| \__ \ -- |_| |_| \__,_|\__,_|___/ -- -- «Prads» (to ".Prads") -- Printable algebraic datatypes. -- See: (find-angg "LUA/Prad1.lua") spaces = function (n) return string.rep(" ", n) end delnewline = function (str) return (str:gsub("\n$", "")) end -- ____ _ ___ _ _ -- | _ \ _ __ __ _ __| |/ _ \ _ _| |_ _ __ _ _| |_ -- | |_) | '__/ _` |/ _` | | | | | | | __| '_ \| | | | __| -- | __/| | | (_| | (_| | |_| | |_| | |_| |_) | |_| | |_ -- |_| |_| \__,_|\__,_|\___/ \__,_|\__| .__/ \__,_|\__| -- |_| -- «PradOutput» (to ".PradOutput") -- The "print"s that are run by a Prad object are "redirected" to a -- PradOutput object. -- PradOutput = Class { new = function () return PradOutput({}) end, type = "PradOutput", __tostring = function (po) return po:tostring("contract") end, __index = { add0 = function (po, line) table.insert(po, line) return po end, add1 = function (po, ctx, line, suffix) return po:add0(ctx.indent .. line .. (suffix or ctx.suffix) .. "\n") end, -- contractible0 = function (po, i) -- if it ends with a "{\n" return po[i]:match("^(.*{)%%?\n$") -- then return its left part end, contractible1 = function (po, j, n) if po[j]:sub(1, n) == spaces(n) -- if its starts with n spaces then return po[j]:sub(n+1) -- then return its right part end end, contractifpossible = function (po, i) local a = po:contractible0(i) local b = a and po:contractible1(i + 1, #a) if b then po[i] = a po[i+1] = b end end, contract = function (po) local po = copy(po) for i=#po-1,1,-1 do po:contractifpossible(i) end return po end, -- tostring = function (po, contract) if contract then po = po:contract() end return delnewline(table.concat(po)) end, }, } -- «PradOutput-tests» (to ".PradOutput-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" po = PradOutput({ "abcd{%\n", " foo\n" }) PPP(po) = po:tostring() = po:tostring("contract") = po --]] -- ____ _ ____ _ _ -- | _ \ _ __ __ _ __| |/ ___|___ _ __ | |_ _____ _| |_ -- | |_) | '__/ _` |/ _` | | / _ \| '_ \| __/ _ \ \/ / __| -- | __/| | | (_| | (_| | |__| (_) | | | | || __/> <| |_ -- |_| |_| \__,_|\__,_|\____\___/|_| |_|\__\___/_/\_\\__| -- -- «PradContext» (to ".PradContext") -- PradContext = Class { type = "PradContext", new = function (indent, suffix) return PradContext {indent=(indent or ""), suffix=(suffix or "")} end, __tostring = mytostringp, __index = { copy = function (pc) return copy(pc) end, set = function (pc, key, val) pc[key] = val; return pc end, copyset = function (pc, key, val) return pc:copy():set(key, val) end, copyindent = function (pc, extraindent) return pc:copyset("indent", pc.indent .. (extraindent or " ")) end, }, } -- «PradContext-tests» (to ".PradContext-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" = PradContext.new() = PradContext.new():copyindent() = PradContext.new():copyindent(" ") = PradContext.new():copy() = PradContext.new():copy():set("foo", "bar") = PradContext.new():copyset("foo", "bar") --]] -- ____ _ ____ _ _ -- | _ \ _ __ __ _ __| / ___|| |_ _ __ _ _ ___| |_ -- | |_) | '__/ _` |/ _` \___ \| __| '__| | | |/ __| __| -- | __/| | | (_| | (_| |___) | |_| | | |_| | (__| |_ -- |_| |_| \__,_|\__,_|____/ \__|_| \__,_|\___|\__| -- -- «PradStruct» (to ".PradStruct") -- The class PradStruct implements a way to print -- the low-level structure of a Prad object... like this: -- -- > a = PradList {"aa", PradSub {b="BEGIN", e="END", 20, 24}, "aaa"} -- > = a:tostruct() -- PradList {( -- 1 = "aa", -- 2 = PradSub {( -- b = "BEGIN", -- e = "END", -- 1 = 20, -- 2 = 24 -- )}, -- 3 = "aaa" -- )} PradStruct = Class { type = "PradStruct", tostring = function (o, ctx) return PradStruct.print(o, nil, ctx):tostring() end, -- comparekeys = function (key1, key2) local type1, type2 = type(key1), type(key2) if type1 ~= type2 then return type1 > type2 else return key1 < key2 end end, sortedkeys = function (A) local lt = PradStruct.comparekeys return sorted(keys(A), lt) end, keyprefix = function (key) if key == nil then return "" end return format("%s = ", key) end, genkvpcs = function (A) return cow(function () local keys = PradStruct.sortedkeys(A) for i,key in ipairs(keys) do local val = A[key] local keyprefix = PradStruct.keyprefix(key) local comma = (i < #keys) and "," or "" coy(key, val, keyprefix, comma) end end) end, be = function (o, keyprefix, comma) keyprefix = keyprefix or "" comma = comma or "" if type(o) ~= "table" then error() end if getmetatable(o) == nil then return keyprefix.."{", "}"..comma end local b = format("%s%s {(", keyprefix, otype(o)) local e = format(")}%s", comma) return b,e end, -- printitem = function (o, out, ctx, key, comma) if type(o) == "table" then local keyprefix = PradStruct.keyprefix(key) local b,e = PradStruct.be(o, keyprefix, comma) local newctx = ctx:copyindent(" ") out:add1(ctx, b) for key,val,keyprefix,comma in PradStruct.genkvpcs(o) do PradStruct.printitem(val, out, newctx, key, comma) end out:add1(ctx, e) else local keyprefix = PradStruct.keyprefix(key) out:add1(ctx, keyprefix..mytostring(o)..(comma or "")) end end, print = function (o, out, ctx, key, comma) if type(ctx) == "string" then ctx = PradContext.new(ctx) end out = out or PradOutput.new() ctx = ctx or PradContext.new() PradStruct.printitem(o, out, ctx, key, comma) return out end, -- __index = { }, } -- «PradStruct-tests» (to ".PradStruct-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" a = {b="BB", e="EE", "a", "aa", 42} b = PradSub {b="BB", e="EE", "a", "aa", 42} c = PradList {b, 333, {"foo", 200}} PP(PradStruct.sortedkeys(a)) for key,val,keyprefix,comma in PradStruct.genkvpcs(a) do print(key,val,keyprefix,comma) end PP(PradStruct.be(a)) PP(PradStruct.be(a, "foo = ", ",")) PP(PradStruct.be(b)) PP(PradStruct.be(b, "foo = ", ",")) out = PradOutput.new() ctx = PradContext.new() PradStruct.print(c, out, ctx) PradStruct.print("foo", out, ctx) PradStruct.print("foo", out, ctx, "k", ",") = out = PradStruct.print(c) = PradStruct.print(c):tostring() = PradStruct.print(c, nil, ":: "):tostring() = PradStruct.tostring(c) = PradStruct.tostring(c, ":: ") --]] -- ____ _ ____ _ -- | _ \ _ __ __ _ __| |/ ___| | __ _ ___ ___ -- | |_) | '__/ _` |/ _` | | | |/ _` / __/ __| -- | __/| | | (_| | (_| | |___| | (_| \__ \__ \ -- |_| |_| \__,_|\__,_|\____|_|\__,_|___/___/ -- -- «PradClass» (to ".PradClass") -- Our printable algebraic datatypes are objects of classes that -- inherit from PradClass. An example: -- -- > = PradList {"aa", PradSub {b="BEGIN", e="END", "20", "42"}, "aaa"} -- aa -- BEGIN -- 20 -- 42 -- END -- aaa -- PradClass = Class { type = "PradClass", from = function (classtable) Class(classtable) setmetatable(classtable.__index, { __index = PradClass.__index }) return classtable end, __index = { add0 = function (prad, out, ctx, line) return out:add0(line) end, add1 = function (prad, out, ctx, line, suffix) return out:add0(ctx.indent .. line .. (suffix or ctx.suffix) .. "\n") end, -- printitem = function (prad, out, ctx, item) if type(item) == "string" then prad:add1(out, ctx, item) else item:print(out, ctx) end end, printitems = function (prad, out, ctx) for i,item in ipairs(prad) do prad:printitem(out, ctx, item) end end, -- tostring = function (prad, out, ctx) return prad:tooutput(out, ctx):tostring("contract") end, tooutput = function (prad, out, ctx) if type(ctx) == "string" then ctx = PradContext.new(ctx) end out = out or PradOutput.new() ctx = ctx or PradContext.new() prad:print(out, ctx) return out end, tostruct = function (prad) return PradStruct.tostring(prad) end, }, } -- «PradList» (to ".PradList") -- PradList and PradSub are the two basic classes "derived" from -- PradClass. They are mostly used for 1) tests, 2) as inspirations -- for the classes PictList and PictSub. PradList = PradClass.from { type = "PradList", __tostring = function (pl) return pl:tostring() end, __index = { print = function (pl, out, ctx) pl:printitems(out, ctx) end, }, } -- «PradSub» (to ".PradSub") -- PradSub = PradClass.from { type = "PradSub", __tostring = function (ps) return ps:tostring() end, __index = { print = function (ps, out, ctx) local newctx = ctx:copyindent() ps:add1(out, ctx, (ps.b or "{")) ps:printitems(out, newctx) ps:add1(out, ctx, (ps.e or "}")) end, }, } -- «PradClass-tests» (to ".PradClass-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" a = PradList {"aa", "aaa"} b = PradList {"bb", a, "bbb"} c = PradSub {"cc", "ccc"} d = PradList {"dd", b, c, "ddd"} e = PradSub {b="BEGIN", e="END", "ee", d, "eee"} = a = b = c = d = d:tostring(nil, ":: ") = e = PradStruct.tostring(e) = PradList {"aa", PradSub {b="BEGIN", e="END", "20", "42"}, "aaa"} --]] -- ____ _ -- _ __ ___ _ __ | _ \ _ __ __ _ __| |___ -- | '_ \ / _ \| '_ \| |_) | '__/ _` |/ _` / __| -- | | | | (_) | | | | __/| | | (_| | (_| \__ \ -- |_| |_|\___/|_| |_|_| |_| \__,_|\__,_|___/ -- -- «nonPrads» (to ".nonPrads") -- Some classes that don't depend on PradClass, -- or that have just a few methods that mention it. -- ____ _ -- / ___|| |__ _____ __ -- \___ \| '_ \ / _ \ \ /\ / / -- ___) | | | | (_) \ V V / -- |____/|_| |_|\___/ \_/\_/ -- -- «Show» (to ".Show") -- Show a chunk of tex code by saving it to 2022pict2e-body.tex, -- latexing 2022pict2e.tex, and displaying the resulting PDF. -- See: (find-LATEX "2022pict2e.tex") -- (find-LATEX "2022pict2e.tex" "load-body") show_dir = os.getenv("PICT2ELUADIR") or "~/LATEX/" Show = Class { type = "Show", new = function (o) return Show {bigstr = tostring(o)} end, try0 = function (bigstr) return Show.new(bigstr):write():compile() end, try = function (bigstr) return Show.try0(Show.preamble..(bigstr or "nil")) end, preamble = "", -- __tostring = function (test) return format("Show: %s => %s", test.fname_body, test.success or "?") end, __index = { fname_body = show_dir.."2022pict2e-body.tex", fname_tex = show_dir.."2022pict2e.tex", -- (find-LATEX "2022pict2e.tex" "load-body") -- write = function (test) ee_writefile(test.fname_body, test.bigstr) return test end, cmd = function (test) local cmd = "cd "..show_dir.. " && lualatex "..test.fname_tex.." < /dev/null" return cmd end, compile = function (test) local log = getoutput(test:cmd()) local success = log:match "Success!!!" Show.log = log test.success = success return test end, print = function (test) print(test); return test end, }, } -- «Show-tests» (to ".Show-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" = Show.try "Hello" * (etv) = Show.try [[$$ \ln x $$]] * (etv) = Show.try() * (etv) --]==] -- __ __ _ ___ __ -- | \/ (_)_ __ (_) \ / / -- | |\/| | | '_ \| |\ \ / / -- | | | | | | | | | \ V / -- |_| |_|_|_| |_|_| \_/ -- -- «MiniV» (to ".MiniV") -- Based on: (find-dn6 "picture.lua" "V") -- but with the code for ZHAs deleted. -- MiniV = Class { type = "MiniV", __tostring = function (v) return pformat("(%s,%s)", v[1], v[2]) end, __add = function (v, w) return V{v[1]+w[1], v[2]+w[2]} end, __sub = function (v, w) return V{v[1]-w[1], v[2]-w[2]} end, __unm = function (v) return v*-1 end, __mul = function (v, w) local ktimesv = function (k, v) return V{k*v[1], k*v[2]} end local innerprod = function (v, w) return v[1]*w[1] + v[2]*w[2] end if type(v) == "number" and type(w) == "table" then return ktimesv(v, w) elseif type(v) == "table" and type(w) == "number" then return ktimesv(w, v) elseif type(v) == "table" and type(w) == "table" then return innerprod(v, w) else error("Can't multiply "..tostring(v).."*"..tostring(w)) end end, -- fromab = function (a, b) if type(a) == "table" then return a elseif type(a) == "number" then return V{a,b} elseif type(a) == "string" then local x, y = a:match("^%((.-),(.-)%)$") if x then return V{x+0, y+0} end -- support for lr coordinates deleted error("V() got bad string: "..a) end end, __index = { todd = function (v) return v[1]..v[2] end, to12 = function (v) return v[1], v[2] end, to_x_y = function (v) return v:to12() end, xy = function (v) return "("..v[1]..","..v[2]..")" end, -- norm = function (v) return (v[1]^2 + v[2]^2)^0.5 end, }, } V = V or MiniV v = V.fromab -- «MiniV-tests» (to ".MiniV-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" V = MiniV v = V.fromab = v(1,2) + 0.1*v(3,4) --]] -- ____ _ _ -- | _ \ ___ (_)_ __ | |_ ___ -- | |_) / _ \| | '_ \| __/ __| -- | __/ (_) | | | | | |_\__ \ -- |_| \___/|_|_| |_|\__|___/ -- -- «Points2» (to ".Points2") -- Points2 = Class { type = "Points2", new = function () return Points2 {} end, from = function (...) return Points2 {...} end, __tostring = function (pts) return pts:tostring() end, __index = { tostring = function (pts, sep) return mapconcat(tostring, pts, sep or "") end, add = function (pts, pt) table.insert(pts, pt) return pts end, adds = function (pts, pts2) for _,pt in ipairs(pts2) do table.insert(pts, pt) end return pts end, rev = function (pts) local pr = Points2.new() for i=#pts,1,-1 do table.insert(pr, pts[i]) end return pr end, -- pict2e = function (pts, prefix) return prefix..tostring(pts) end, Line = function (pts) return pts:pict2e("\\Line") end, polygon = function (pts) return pts:pict2e("\\polygon") end, region0 = function (pts) return pts:pict2e("\\polygon*") end, polygon = function (pts, s) return pts:pict2e("\\polygon"..(s or "")) end, -- region = function (pts, color) return pts:region0():color(color) end, -- region = function (pts, color) return pts:region0() end, -- }, } -- «Points2-tests» (to ".Points2-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" pts = Points2 {v(1,2), v(3,4), v(3,1)} = pts = pts:Line() = pts:rev() = pts:add(pts:rev()) pts = Points2 {v(1,2), v(3,4), v(3,1)} PPP(pts:Line()) Points2.__index.pict2e = function (pts, prefix) return PictList { prefix..tostring(pts) } end PPP(pts:Line()) = pts:Line() = pts:Line():bshow() * (etv) = pts:polygon() = pts:polygon():bshow() * (etv) = pts:region0():bshow() * (etv) --]] -- ____ _ _ ____ __ __ _ -- | _ \(_) ___| |_|___ \ __\ \ / /__ ___| |_ ___ _ __ -- | |_) | |/ __| __| __) / _ \ \ / / _ \/ __| __/ _ \| '__| -- | __/| | (__| |_ / __/ __/\ V / __/ (__| || (_) | | -- |_| |_|\___|\__|_____\___| \_/ \___|\___|\__\___/|_| -- -- «Pict2eVector» (to ".Pict2eVector") -- Based on: (find-dn6 "picture.lua" "pict2e-vector") Pict2eVector = Class { type = "Pict2eVector", lowlevel = function (x0, y0, x1, y1) local dx, dy = x1-x0, y1-y0 local absdx, absdy = math.abs(dx), math.abs(dy) local veryvertical = absdy > 100*absdx local f = function (Dx,Dy,len) return Dx,Dy, len end if veryvertical then if dy > 0 then return f( 0,1, dy) else return f( 0,-1, -dy) end else if dx > 0 then return f(dx,dy, dx) else return f(dx,dy, -dx) end end end, -- eps = 1/4, latex = function (x0, y0, x1, y1) local norm = math.sqrt((x1-x0)^2 + (y1-y0)^2) if norm < Pict2eVector.eps then return pformat("\\put%s{}", v(x0,y0)) -- if very short draw nothing end local Dx,Dy, len = Pict2eVector.lowlevel(x0, y0, x1, y1) return pformat("\\put%s{\\vector%s{%s}}", v(x0,y0), v(Dx,Dy), len) end, fromto = function (x0y0, x1y1) local x0,y0, x1,y1 = x0y0[1],x0y0[2], x1y1[1],x1y1[2] return Pict2eVector.latex(x0,y0, x1,y1) end, fromwalk = function (x0y0, dxdy) return Pict2eVector.fromto(x0y0, x0y0+dxdy) end, __index = { }, } -- «Pict2eVector-tests» (to ".Pict2eVector-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" x0y0 = v(3,2) = x0y0 f = function (ang, len) return Pict2eVector.fromwalk(x0y0, v(math.cos(ang),math.sin(ang))*len) end = f(0, 2) PPP(f(0, 2)) p = PictList{} for i=0,1.5,1/8 do p:addobj(f(i*math.pi, i*2)) end = p = p:bshow() * (etv) r = Pict2e.region0(v(0,0), v(2,0), v(0,2)) q = PictList { r:color("red") :putat(v(1, 1)), r:color("orange"):putat(v(1, 2)), p } = q = q:bshow() * (etv) --]==] -- ____ _ _ ____ -- | _ \(_) ___| |_|___ \ ___ -- | |_) | |/ __| __| __) / _ \ -- | __/| | (__| |_ / __/ __/ -- |_| |_|\___|\__|_____\___| -- -- «Pict2e» (to ".Pict2e") -- Pict2e objects are implemented using the PradClass defined in the -- first part of this file, and they have lots of methods that use and -- call the "nonPrad" classes defined in the second part of this file. -- -- THIS IS A FAKE CLASS. -- -- The "objects of the class Pict2e" are in reality objects of the -- classes PictList and PictSub, defined below, that are derived from -- PradClass. -- -- See: (find-LATEX "2022pict2e.lua" "Pict2e") Pict2e = Class { type = "Pict2e", line = function (...) return PictList({}):addline(...) end, polygon = function (...) return PictList({}):addpolygon(...) end, region0 = function (...) return PictList({}):addregion0(...) end, -- bounds = nil, getbounds = function () return Pict2e.bounds or PictBounds.new(v(0,0), v(3, 2)) end, -- __index = { }, } -- «PictList» (to ".PictList") -- «PictSub» (to ".PictSub") PictList = PradClass.from { type = "PictList", __tostring = function (pl) return pl:tostring() end, __index = { print = function (pl, out, ctx) pl:printitems(out, ctx) end, }, } PictSub = PradClass.from { type = "PictSub", __tostring = function (ps) return ps:tostring() end, __index = { print = function (ps, out, ctx) local newctx = ctx:copyindent() ps:add1(out, ctx, (ps.b or "{")) ps:printitems(out, newctx) ps:add1(out, ctx, (ps.e or "}")) end, }, } -- «Pict2e-tests» (to ".Pict2e-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" p = PictList {} = p:addobj("% foo") = p:addline(v(1,2), v(3,4)) = p:addline(v(1,2), v(3,4), v(5,6)) = Pict2e.line(v(1,2), v(3,4), v(5,6)) = Pict2e.line(v(1,2), v(3,4), v(5,6)):precolor("red") = Pict2e.line(v(1,2), v(3,4), v(5,6)):color("red") = Pict2e.region0(v(1,2), v(3,4), v(3,1)):color("red") --]] -- «Pict2e-methods» (to ".Pict2e-methods") -- These methods transform Pict2e objects. -- As Pict2e objects are objects of the classes PradList and PradSub, -- that are derived from PradClass, these methods are added to -- PradClass. PradClass.__index.def = function (pis, name) local b = "\\def\\"..name.."{{" local e = "}}" return PradSub({b=b, pis, e=e}) end PradClass.__index.sa = function (pis, name) local b = "\\sa{"..name.."}{{" local e = "}}" return PradSub({b=b, pis, e=e}) end PradClass.__index.Color = function (pis, color) local b = "\\Color"..color.."{" local e = "}" return PradSub({b=b, e=e, pis}) end PradClass.__index.precolor = function (pis, color) local c = "\\color{"..color.."}" return PradList({c, pis}) end PradClass.__index.prethickness = function (pis, thickness) local c = "\\linethickness{"..thickness.."}" return PradList({c, pis}) end PradClass.__index.preunitlength = function (pis, unitlength) local c = "\\unitlength="..unitlength return PradList({c, pis}) end PradClass.__index.bhbox = function (pis) local b = "\\bhbox{$" local e = "$}" return PradSub({b=b, pis, e=e}) end PradClass.__index.myvcenter = function (pis) local b = "\\myvcenter{" local e = "}" return PradSub({b=b, pis, e=e}) end PradClass.__index.putat = function (pis, xy) local b = pformat("\\put%s{", xy) local e = "}" return PradSub({b=b, pis, e=e}) end PradClass.__index.color = function (pis, color) return PictSub({pis:precolor(color)}) end PradClass.__index.addobj = function (pis, o) table.insert(pis, o) return pis end PradClass.__index.addputstrat = function (pis, xy, str) return pis:addobj(pformat("\\put%s{%s}", xy, str)) end PradClass.__index.addopendotat = function (pis, xy) return pis:addputstrat(xy, "\\opendot") end PradClass.__index.addcloseddotat = function (pis, xy) return pis:addputstrat(xy, "\\closeddot") end PradClass.__index.addline = function (pis, ...) local pts = Points2.from(...) return pis:addobj(pts:Line()) end PradClass.__index.addpolygon = function (pis, ...) local pts = Points2.from(...) return pis:addobj(pts:polygon()) end PradClass.__index.addregion0 = function (pis, ...) local pts = Points2.from(...) return pis:addobj(pts:region0()) end PradClass.__index.bshow0 = function (p, str) return p:pgat(str or "pgat"):dd():tostringp() end PradClass.__index.bshow = function (p, ...) return Show.try(p:bshow0(...)) end PradClass.__index.output = function (p) -- for dednat6 return output(p:tostringp()) end PradClass.__index.setbounds = function (p, ...) Pict2e.bounds = PictBounds.new(...) return p end -- «Pict2e-methods-tests» (to ".Pict2e-methods-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" p = PictList {} = p:addobj("% foo") = p:addline(v(1,2), v(3,4)) = p:addline(v(1,2), v(3,4), v(5,6)) = Pict2e.line(v(1,2), v(3,4), v(5,6)) = Pict2e.line(v(1,2), v(3,4), v(5,6)):precolor("red") = Pict2e.line(v(1,2), v(3,4), v(5,6)):color("red") = Pict2e.line(v(1,2), v(3,4), v(5,6)):Color("Red") = Pict2e.polygon(v(1,2), v(3,4), v(3,1)):color("red") = Pict2e.polygon(v(1,2), v(3,4), v(3,1)):color("red"):bshow0() = Pict2e.polygon(v(1,2), v(3,4), v(3,1)):color("red"):bshow() * (etv) = Pict2e.region0(v(1,2), v(3,4), v(3,1)):color("red"):bshow() * (etv) Pict2e.bounds = PictBounds.new(v(0,0), v(4,4)) = Pict2e.region0(v(1,2), v(3,4), v(3,1)):color("red"):bshow() * (etv) -- (find-LATEX "2021-2-C3-bezier.tex" "exercicio-3-figs") tof = function (str) return Code.ve(format("t => v(t,%s)", str)) end = tof "t*t" = tof "t*t" (4) pi, sin, cos = math.pi, math.sin, math.cos ts = seq(0, 2*pi, pi/16) xys = map(tof "sin(t)", ts) toplot = function (ts, strexpr, color) return Pict2e.line(myunpack(map(tof(strexpr), ts))):color(color) end = Pict2e.line(myunpack(xys)):color("red") = toplot(ts, "t*t", "yellow") body = PictList { toplot(ts, "sin(t)", "red"), toplot(ts, "cos(t)", "orange"), toplot(ts, "2*sin(2*t)", "DarkGreen") } = body Pict2e.bounds = PictBounds.new(v(0,-2), v(7,2)) = body:bshow() * (etv) --]] -- ____ _ _ ____ _ -- | _ \(_) ___| |_| __ ) ___ _ _ _ __ __| |___ -- | |_) | |/ __| __| _ \ / _ \| | | | '_ \ / _` / __| -- | __/| | (__| |_| |_) | (_) | |_| | | | | (_| \__ \ -- |_| |_|\___|\__|____/ \___/ \__,_|_| |_|\__,_|___/ -- -- «PictBounds» (to ".PictBounds") -- (find-LATEX "edrxpict.lua" "pictp0-pictp3") -- (find-es "pict2e" "picture-mode") -- (find-kopkadaly4page (+ 12 288) "\\begin{picture}(x dimen,y dimen)") -- (find-kopkadaly4text (+ 12 288) "\\begin{picture}(x dimen,y dimen)") -- (find-kopkadaly4page (+ 12 301) "13.1.6 Shifting a picture environment") -- (find-kopkadaly4text (+ 12 301) "13.1.6 Shifting a picture environment") -- (find-kopkadaly4page (+ 12 302) "\\begin{picture}(x dimen,y dimen)(x offset,y offset)") -- (find-kopkadaly4text (+ 12 302) "\\begin{picture}(x dimen,y dimen)(x offset,y offset)") PictBounds = Class { type = "PictBounds", new = function (ab, cd, e) local a,b = ab[1], ab[2] local c,d = cd[1], cd[2] local x1,x2 = min(a,c), max(a,c) local y1,y2 = min(b,d), max(b,d) return PictBounds {x1=x1, y1=y1, x2=x2, y2=y2, e=e or .2} end, __tostring = function (pb) return pb:tostring() end, __index = { x0 = function (pb) return pb.x1 - pb.e end, x3 = function (pb) return pb.x2 + pb.e end, y0 = function (pb) return pb.y1 - pb.e end, y3 = function (pb) return pb.y2 + pb.e end, p0 = function (pb) return v(pb.x1 - pb.e, pb.y1 - pb.e) end, p1 = function (pb) return v(pb.x1, pb.y1 ) end, p2 = function (pb) return v(pb.x2, pb.y2 ) end, p3 = function (pb) return v(pb.x2 + pb.e, pb.y2 + pb.e) end, tostring = function (pb) return pformat("LL=(%s,%s) UR=(%s,%s) e=%s", pb.x1, pb.y1, pb.x2, pb.y2, pb.e) end, -- beginpicture = function (pb) local dimen = pb:p3() - pb:p0() local center = (pb:p3() + pb:p0()) * 0.5 local offset = pb:p0() return pformat("\\begin{picture}%s%s", dimen, offset) end, -- grid = function (pb) local p = PictList({"% Grid", "% Horizontal lines:"}) for y=pb.y1,pb.y2 do p:addline(v(pb:x0(), y), v(pb:x3(), y)) end p:addobj("% Vertical lines:") for x=pb.x1,pb.x2 do p:addline(v(x, pb:y0()), v(x, pb:y3())) end return p end, ticks = function (pb, e) e = e or .2 local p = PictList({"% Ticks", "% On the vertical axis:"}) for y=pb.y1,pb.y2 do p:addline(v(-e, y), v(e, y)) end p:addobj("% On the horizontal axis: ") for x=pb.x1,pb.x2 do p:addline(v(x, -e), v(x, e)) end return p end, axes = function (pb) local p = PictList({"% Axes"}) return p:addline(v(pb:x0(), 0), v(pb:x3(), 0)) :addline(v(0, pb:y0()), v(0, pb:y3())) end, axesandticks = function (pb) return PictList { pb:axes(), pb:ticks() } end, }, } -- «PictBounds-tests» (to ".PictBounds-tests") -- (find-LATEX "edrxpict.lua" "pictp0-pictp3") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" = PictBounds.new(v(-1,-2), v( 3, 5)) = PictBounds.new(v( 3, 5), v(-1,-2)) = PictBounds.new(v( 3, 5), v(-1,-2), 0.5) pb = PictBounds.new(v(-1,-2), v( 3, 5)) = pb:p0() = pb:p1() = pb:p2() = pb:p3() = pb:grid() = pb:ticks() = pb:axes() = pb:axesandticks() = pb:grid():prethickness("0.5pt"):color("gray") = pb = pb:beginpicture() = pb:p0() = (pb:p0() + pb:p3()) = (pb:p0() + pb:p3()) * 0.5 --]] -- ____ _ _ ____ _ -- | _ \(_) ___| |_| __ ) ___ _ _ _ __ __| |___ _ -- | |_) | |/ __| __| _ \ / _ \| | | | '_ \ / _` / __|_| |_ -- | __/| | (__| |_| |_) | (_) | |_| | | | | (_| \__ \_ _| -- |_| |_|\___|\__|____/ \___/ \__,_|_| |_|\__,_|___/ |_| -- -- «PictBounds-methods» (to ".PictBounds-methods") -- (find-LATEX "2022pict2e.tex" "grid-axes-ticks") -- Methods that use PictBounds and that transform Pict2e objects. -- They are installed in PradClass, and are used mainly by :pgat(). PradClass.__index.bep = function (p) local b = Pict2e.getbounds():beginpicture() local e = "\\end{picture}" return PradSub({b=b, e=e, p}) end PradClass.__index.pregrid = function (p) local grid0 = Pict2e.getbounds():grid() local grid = PradSub { "\\pictgridstyle", grid0 } return PradList({grid, p}) end PradClass.__index.preaxesandticks = function (p) local axesandticks0 = Pict2e.getbounds():axesandticks() local axesandticks = PradSub { "\\pictaxesstyle", axesandticks0 } return PradList({axesandticks, p}) end PradClass.__index.prenaxesandticks = function (p) local axesandticks0 = Pict2e.getbounds():axesandticks() local axesandticks = PradSub { "\\pictnaxesstyle", axesandticks0 } return PradList({axesandticks, p}) end PradClass.__index.preaxes = function (p) local axesandticks0 = Pict2e.getbounds():axes() local axesandticks = PradSub { "\\pictaxesstyle", axesandticks0 } return PradList({axesandticks, p}) end -- "PGAT" means "Picture, Grid, Axes, Ticks". -- This method adds begin/end picture, grid, axes, and ticks to a -- Pict2e object, in the right order, and with a very compact syntax -- to select what will be added. It can also add a bhbox and a def. -- PradClass.__index.pgat = function (p, str, def) if str:match("a") then p = p:preaxesandticks() end if str:match("A") then p = p:preaxes() end if str:match("N") then p = p:prenaxesandticks() end -- for numerozinhos if str:match("g") then p = p:pregrid() end if str:match("p") then p = p:bep() end if str:match("c") then p = p:myvcenter() end if str:match("B") then p = p:bhbox() end if def then p = p:def(def) end return p end -- Surround with dollars and double dollars. PradClass.__index.d = function (p) return PradSub({b="$", e="$", p}) end PradClass.__index.dd = function (p) return PradSub({b="$$", e="$$", p}) end PradClass.__index.scalebox = function (p, scale) if not scale then return p end local b = "\\scalebox{"..scale.."}{$" local e = "$}" return PradSub({b=b, p, e=e}) end -- Like :tostring(), but adds a percent to the end of each line. PradClass.__index.tostringp = function (p, ...) return p:tostring(nil, PradContext.new(nil, "%")) end -- «PictBounds-methods-tests» (to ".PictBounds-methods-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" = Pict2e.line(v(1,2), v(3,4)):pregrid() = Pict2e.line(v(1,2), v(3,4)):pregrid():preaxesandticks() = Pict2e.line(v(1,2), v(3,4)):pregrid():preaxes() = Pict2e.line(v(1,2), v(3,4)):bep() = Pict2e.line(v(1,2), v(3,4)):pgat("pgat") = Pict2e.line(v(1,2), v(3,4)):pgat("pAt") = Pict2e.line(v(1,2), v(3,4)):pgat("pB", "foo") = Pict2e.line(v(1,2), v(3,4)):pgat("pB"):d() = Pict2e.line(v(1,2), v(3,4)):pgat("pB"):dd() o = Pict2e.line(v(1,2), v(3,4)):pgat("pgatB"):dd() = o:tostring() = o:tostring(nil, ":: ") = o:tostring(nil, PradContext.new(":: ", "%")) = o:tostring(nil, PradContext.new(nil, "%")) = o:tostringp() = Show.try(o:tostringp()) * (etv) Pict2e.bounds = PictBounds.new(v(0,0), v(3, 2), 0.7) o = Pict2e.line(v(1,2), v(3,4)):pgat("pgat"):dd() = o = o:tostringp() = Show.try(o:tostringp()) * (etv) --]] -- «fake_ln_mod_x» (to ".fake_ln_mod_x") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pict2e1.lua" Pict2e.bounds = PictBounds.new(v(-5,-5), v(5,5)) fake_ln_mod_x = function (C1, C2) return PictList({}) :addline(v(-4, 3+C1), v(-3, 3+C1), v(-2, 2+C1), v(-1, 0+C1), v(-0,-3+C1)) :addline(v( 4, 3+C2), v( 3, 3+C2), v( 2, 2+C2), v( 1, 0+C2), v( 0,-3+C2)) :addopendotat(v(-0,-3+C1)) :addopendotat(v( 0,-3+C2)) end = fake_ln_mod_x(0, 0) = fake_ln_mod_x(1, 2) = fake_ln_mod_x(0, 0):bshow() * (etv) Pict2e.bounds = PictBounds.new(v(-5,-5), v(5,5)) Pict2e.bounds = PictBounds.new(v(-4,-4), v(4,4)) = fake_ln_mod_x(1, -1):bshow() * (etv) --]] -- Local Variables: -- coding: utf-8-unix -- End: