From 9a1b9756939e12e328dea3633d9fe3cbde8f154b Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Wed, 8 Apr 2020 15:36:51 +0200 Subject: 2020-04-08 14:37:00 --- tex/context/base/mkiv/meta-imp-experiments.mkxl | 360 ++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 tex/context/base/mkiv/meta-imp-experiments.mkxl (limited to 'tex/context/base/mkiv/meta-imp-experiments.mkxl') diff --git a/tex/context/base/mkiv/meta-imp-experiments.mkxl b/tex/context/base/mkiv/meta-imp-experiments.mkxl new file mode 100644 index 000000000..6b43ba676 --- /dev/null +++ b/tex/context/base/mkiv/meta-imp-experiments.mkxl @@ -0,0 +1,360 @@ +%D \module +%D [ file=meta-imp-experiments, +%D version=2020.03.18, +%D title=\METAPOST\ Graphics, +%D subtitle=Experimental Graphics, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D This library implements some experimental functionality that eventually +%D might end up someplace else. + +\startluacode + + -- I decided to play with this kind of graphics after I read an article in a Dutch + -- popular science journal. It was an article about virusus in the mids of the time + -- when covid raged, so it also was a distraction. + + -- This is a typical case of first prototyping it in Lua using the 'context' command + -- to generate MetaPost code and when that worked okay do it the following way. The + -- way data is passed is a bit messy. + + do + + local function sum(t) + local n = 0 + for i=1,#t do + n = n + t[i] + end + return n + end + + local function checked(data) + if data then + local n = #data + for i=1,n do + data[i][i] = 0 + end + for i=1,n do + local di = data[i] + for j=i+1,n do + local dj = data[j] + local dji = dj[i] + if not dji then + dji = 0 + dj[i] = 0 + end + di[j] = dji + end + end + return data + else + return { } + end + end + + local data, list = nil, nil + + function mp.lmt_overlap_prepare() + data = checked(metapost.getparameter { "data" }) + list = { } + for i=1,#data do + list[i] = sum(data[i]) + end + end + + function mp.lmt_overlap_reset() + data = nil + list = nil + end + + function mp.lmt_overlap_n() + return #list + end + + function mp.lmt_overlap_data(i, j) + if j then + return data[i][j] + else + return list[i] + end + end + + local injectstring = mp.inject.string + + function mp.lmt_overlap_text(i, j) + injectstring(data[i][j] or "") + end + + function mp.lmt_overlap_label(i) + local labels = metapost.getparameter { "labels" } + injectstring(labels and labels[i] or "") + end + + function mp.lmt_overlap_color(i) + local colors = metapost.getparameter { "colors" } + injectstring(colors and colors[i] or "darkgray") + end + + function mp.lmt_overlap_total() + return sum(list) + end + + end +\stopluacode + +\startMPextensions + +presetparameters "overlap" [ + options = "paths,lines", + gap = 4, + subgap = 2, + offset = 8, + color = "darkgray", + alternative = "circular", + colors = { + "darkred", + "darkgreen", + "darkblue", + "darkyellow", + "darkmagenta", + "darkcyan" + }, +] ; + +def lmt_overlap = applyparameters "overlap" "lmt_do_overlap" enddef ; + +vardef lmt_do_overlap_circular = + + astep := 360 / steps ; + + p := fullcircle scaled steps ; + r := origin -- (2*steps,0) ; + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) ; + first := start ; + last := stop ; + for j=1 upto n: + if i <> j : + last := first + lua.mp.lmt_overlap_data(i,j) ; + a := p intersectionpoint (r rotated (first * astep + 0.1)) ; % the 0.1 is somehow needed, why + b := p intersectionpoint (r rotated (last * astep - 0.1)) ; % the 0.1 is somehow needed, why + qq[i][j] := (p cutafter b) cutbefore a ; + first := last + subgap ; + fi ; + endfor ; + start := stop + gap + (n - 1) * subgap ; + endfor ; + + if hasoption "options" "paths" : + + for i=1 upto n : + for j=1 upto n : + if i <> j : + q := qq[i][j] ; + freelabeloffset := getparameter "offset" ; + freelabel(lua.mp.lmt_overlap_text(i,j), point .5 along q, origin) ; + if i < j : + s := qq[j][i] ; + a := point length(q) of q ; + b := point 0 of s ; + c := point length(s) of s ; + d := point 0 of q ; + q := q & a .. controls origin and origin .. b & s & c .. controls origin and origin .. d -- cycle ; + fill q withcolor lua.mp.lmt_overlap_color(i) withtransparency (1,.8) ; + fi ; + fi ; + endfor ; + endfor ; + + fi ; + + if hasoption "options" "lines" : + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) + (n - 2) * subgap ; + a := p intersectionpoint (r rotated (start * astep)) ; + b := p intersectionpoint (r rotated (stop * astep)) ; + q := (p cutbefore a) cutafter b ; + freelabeloffset := getparameterdefault "textoffset" (4 * getparameter "offset") ; + freelabel(lua.mp.lmt_overlap_label(i), point .5 along q, origin) ; + draw q withcolor white withpen pencircle scaled 5 ; + draw q withcolor getparameter "color" withpen pencircle scaled 5 ; + start := stop + gap + subgap ; + endfor ; + + fi ; + +enddef ; + +vardef lmt_do_overlap_linear = + astep := 1 ; % 1.25 + + p := origin -- (astep * steps,0) ; + r := origin -- (0,astep * steps) ; + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) ; + first := start ; + last := stop ; + for j=1 upto n: + if i <> j : + last := first + lua.mp.lmt_overlap_data(i,j) ; + qq[i][j] := (first * astep,0) -- (last * astep,0) ; + first := last + subgap ; + fi ; + endfor ; + start := stop + gap + (n - 1) * subgap ; + endfor ; + + if hasoption "options" "paths" : + + for i=1 upto n : + for j=1 upto n : + if i < j : + qq[i][j] := qq[i][j] { up } .. { down } qq[j][i] { up } .. { down} cycle ; + fill qq[i][j] withcolor lua.mp.lmt_overlap_color(i) withtransparency (1,.8) ; + fi ; + endfor ; + endfor ; + + for i=1 upto n : + for j=1 upto n : + if i < j : + t := thelabel(lua.mp.lmt_overlap_text(i,j), (center topboundary qq[i][j]) ) ; + fill boundingbox t enlarged (ExHeight/2) withcolor white ; + draw t ; + fi ; + endfor ; + endfor ; + + fi ; + + if hasoption "options" "lines" : + + start := 0 ; + stop := 0 ; + for i=1 upto n: + stop := start + lua.mp.lmt_overlap_data(i) + (n - 2) * subgap ; + q := (start * astep,0) -- (stop * astep,0) ; + freelabeloffset := getparameterdefault "textoffset" (4 * getparameter "offset") ; + label.bot(lua.mp.lmt_overlap_label(i), (point .5 along q) shifted (0,- freelabeloffset/4)) ; + draw q withcolor white withpen pencircle scaled 5 ; + draw q withcolor getparameter "color" withpen pencircle scaled 5 ; + start := stop + gap + subgap ; + endfor ; + + fi ; + +enddef ; + +vardef lmt_do_overlap = + image ( + + lmt_load_mlib_cnt ; + + pushparameters "overlap" ; + + save p, q, r, s, qq, a, b, c, d, t, n, gap, subgap, steps, astep, start, stop, first, last ; + path p, q, r, s, qq[][] ; + pair a, b, c, d ; + picture t ; + numeric n, gap, subgap, steps, astep, start, stop, first, last ; + save freelabeloffset; freelabeloffset := 8 ; + interim linecap := butt; + interim linejoin := squared; + + lua.mp.lmt_overlap_prepare() ; + + n := lua.mp.lmt_overlap_n(); + gap := getparameter "gap" ; + subgap := getparameter "subgap" ; + steps := lua.mp.lmt_overlap_total() + (n * gap) + n * (n - 1) * subgap ; + + if ((getparameter "alternative") = "linear") or ((getparameter "alternative") = "line") : + lmt_do_overlap_linear ; + else : + lmt_do_overlap_circular ; + fi ; + + lua.mp.lmt_overlap_reset() ; + + popparameters ; + ) +enddef ; + +\stopMPextensions + +\continueifinputfile{meta-imp-experiments.mkxl} + +% \useMPlibrary[experiments] + +\usemodule[article-basic] + +\starttext + +% todo: datafile: { data = { }, labels = { } } + +% % data = { +% % { 0, 10, 30, 10, 20 }, +% % { 10, 0, 10, 20, 10 }, +% % { 30, 10, 0, 5, 15 }, +% % { 10, 20, 5, 0, 5 }, +% % { 20, 10, 15, 5, 0 } +% % }, +% % data = { +% % { 0 }, +% % { 10, 0 }, +% % { 30, 10, 0 }, +% % { 10, 20, 5, 0 }, +% % { 20, 10, 15, 5, 0 } +% % }, +% data = { +% { }, +% { 10 }, +% { 30, 10 }, +% { 10, 20, 5 }, +% { 20, 10, 15, 5 } +% }, + +\startbuffer +\startMPcode{doublefun} + draw lmt_overlap [ + alternative = "circular", + data = { { }, { 10 }, { 30, 10 }, { 10, 20, 5 }, { 20, 10, 15, 5 } }, + labels = { "one", "two", "three", "four", "five" } + ] ; +\stopMPcode +\stopbuffer + +\startlinecorrection[blank] + \getbuffer +\stoplinecorrection + +\startbuffer +\startMPcode{doublefun} + draw lmt_overlap [ + alternative = "linear", + data = { { }, { 10 }, { 30, 10 }, { 10, 20, 5 }, { 20, 10, 15, 5 } }, + labels = { "one", "two", "three", "four", "five" } + ] ; +\stopMPcode +\stopbuffer + +\startlinecorrection[blank] + \getbuffer +\stoplinecorrection + +\stoptext -- cgit v1.2.3