diff options
author | Karl Berry <karl@freefriends.org> | 2024-12-09 21:18:16 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2024-12-09 21:18:16 +0000 |
commit | bd01b8f1508b38fabf50da4ad8fbac6497697ba5 (patch) | |
tree | 515068e80d87595ecb606d7dbb3d4003b00407ed | |
parent | e4c71587aa7865ccd8d4c83a4daf3d1b04c6da6c (diff) |
luatikz (9dec24)
git-svn-id: svn://tug.org/texlive/trunk@73087 c570f23f-e606-0410-a88d-b1316a301751
36 files changed, 2730 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/luatikz/README.txt b/Master/texmf-dist/doc/latex/luatikz/README.txt new file mode 100644 index 00000000000..14930dc4d36 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/README.txt @@ -0,0 +1,9 @@ +----------------- +Luatikz is a graphics library to draw tikz graphics +using the Lua programming language. +----------------- + +License: + +LaTeX Project Public License 1.3c +MIT License (expat) diff --git a/Master/texmf-dist/doc/latex/luatikz/example/bezier2.lua b/Master/texmf-dist/doc/latex/luatikz/example/bezier2.lua new file mode 100644 index 00000000000..55f7766ec06 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/bezier2.lua @@ -0,0 +1,11 @@ +tikz.within( '*' ) + +local bz = + bezier2{ + p1 = p{ 0, 0 }, + pc = p{ 2, 2 }, + p2 = p{ 4, 0 }, + } + +draw{ line_width=1, bz } +bz.drawHelpers( 'p' ) diff --git a/Master/texmf-dist/doc/latex/luatikz/example/bezier3a.lua b/Master/texmf-dist/doc/latex/luatikz/example/bezier3a.lua new file mode 100644 index 00000000000..5c91a4238f8 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/bezier3a.lua @@ -0,0 +1,12 @@ +tikz.within( '*' ) + +local bz = + bezier3{ + p1 = p{ 0, 0 }, + pc1 = p{ 1, 2 }, + pc2 = p{ 3, 3 }, + p2 = p{ 4, 0 }, + } + +draw{ line_width=1, bz } +bz.drawHelpers( 'p' ) diff --git a/Master/texmf-dist/doc/latex/luatikz/example/bezier3b.lua b/Master/texmf-dist/doc/latex/luatikz/example/bezier3b.lua new file mode 100644 index 00000000000..54a2a982ce5 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/bezier3b.lua @@ -0,0 +1,32 @@ +tikz.within( '*' ) + +local bz = + bezier3{ + p1 = p{ 0, 0 }, + pc1 = p{ 1, 2 }, + pc2 = p{ 3, 3 }, + p2 = p{ 4, 0 }, + } + +draw{ line_width = 1, bz } + +for t = 0, 1, 0.1 +do + local pt = bz.pt( t ) + draw{ + fill = black, + circle{ + at = pt, + radius = 0.05, + } + } + + local phit = bz.phit( t ) + math.pi / 2 + draw{ + line{ + p1 = pt, + phi = phit, + length = 1, + } + } +end diff --git a/Master/texmf-dist/doc/latex/luatikz/example/blinea.lua b/Master/texmf-dist/doc/latex/luatikz/example/blinea.lua new file mode 100644 index 00000000000..8a49476e511 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/blinea.lua @@ -0,0 +1,23 @@ +tikz.within( '*' ) + +local l1 = bline{ p{ 0, 0 }, p{ 2, 3 }, bend_right = 45 } +local l2 = bline{ p{ 0, 3 }, p{ 2, 1 }, bend_left = 30 } + +draw{ draw=red, l1 } +draw{ draw=blue, l2 } +put{ + node{ + at = l1.pc, + anchor = south, + rotate = l1.line.phi * 180 / math.pi, + text = 'red', + } +} +put{ + node{ + at = l2.pc, + anchor = south, + rotate = l2.line.phi * 180 / math.pi, + text = 'blue', + } +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/circle.lua b/Master/texmf-dist/doc/latex/luatikz/example/circle.lua new file mode 100644 index 00000000000..ba85c04e5ad --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/circle.lua @@ -0,0 +1,12 @@ +tikz.within( '*' ) + +draw{ + circle{ + at = p{ 0, 0 }, + radius = 2, + }, + circle{ + at = p{ 2, 1 }, + radius = 1, + } +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/curvea.lua b/Master/texmf-dist/doc/latex/luatikz/example/curvea.lua new file mode 100644 index 00000000000..b1d6b85506b --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/curvea.lua @@ -0,0 +1,14 @@ +tikz.within( '*' ) + +local c = + curve{ + points = + { + p{ 0, 0 }, + p{ 2, 2 }, + p{ 4, 0 }, + }, + } + +draw{ line_width=1, c } +c.drawHelpers( 'p' ) diff --git a/Master/texmf-dist/doc/latex/luatikz/example/curveb.lua b/Master/texmf-dist/doc/latex/luatikz/example/curveb.lua new file mode 100644 index 00000000000..194127837a7 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/curveb.lua @@ -0,0 +1,16 @@ +tikz.within( '*' ) + +local c = + curve{ + points = + { + p{ 0, 0 }, + p{ 2, 2 }, + p{ 4, 0 }, + }, + cycle = true, + tension = 1.0, + } + +draw{ line_width=1, c } +c.drawHelpers( 'p' ) diff --git a/Master/texmf-dist/doc/latex/luatikz/example/ellipse.lua b/Master/texmf-dist/doc/latex/luatikz/example/ellipse.lua new file mode 100644 index 00000000000..c648e813203 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/ellipse.lua @@ -0,0 +1,14 @@ +tikz.within( '*' ) + +draw{ + ellipse{ + at = p{ 0, 0 }, + xradius = 3, + yradius = 2, + }, + ellipse{ + at = p{ 2, 1 }, + xradius = 1.5, + yradius = 1, + } +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/ellipseArc.lua b/Master/texmf-dist/doc/latex/luatikz/example/ellipseArc.lua new file mode 100644 index 00000000000..97536d3836d --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/ellipseArc.lua @@ -0,0 +1,18 @@ +tikz.within( '*' ) + +draw{ + ellipseArc{ + at = p{ 0, 0 }, + from = 0, + to = 90, + xradius = 3, + yradius = 2, + }, + ellipseArc{ + at = p{ 2, 1 }, + xradius = 1.5, + yradius = 1, + from = -45, + to = 45, + } +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/immute1.lua b/Master/texmf-dist/doc/latex/luatikz/example/immute1.lua new file mode 100644 index 00000000000..39b0e08a420 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/immute1.lua @@ -0,0 +1,4 @@ +tikz.within( '*' ) + +local p1 = p{ 1, 1 } +p1.x = p1.x + 2 diff --git a/Master/texmf-dist/doc/latex/luatikz/example/immute2.lua b/Master/texmf-dist/doc/latex/luatikz/example/immute2.lua new file mode 100644 index 00000000000..3c69f4b6b52 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/immute2.lua @@ -0,0 +1,6 @@ +tikz.within( '*' ) + +local p1 = p{ 1, 1 } +p1 = p{ p1.x + 2, p1.y } +-- or +p1 = p1 + p{ 2, 0 } diff --git a/Master/texmf-dist/doc/latex/luatikz/example/intro.lua b/Master/texmf-dist/doc/latex/luatikz/example/intro.lua new file mode 100644 index 00000000000..9752fd464ea --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/intro.lua @@ -0,0 +1,8 @@ +tikz.within( '*' ) + +local p1 = p{ 1, 1 } +local p2 = p{ 6, 2 } +local l1 = line{ p1, p2 } + +draw{ l1 } +draw{ line{ p{ 2, 2 }, p{ 3, 3 } } } diff --git a/Master/texmf-dist/doc/latex/luatikz/example/linea.lua b/Master/texmf-dist/doc/latex/luatikz/example/linea.lua new file mode 100644 index 00000000000..fcc4a78989e --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/linea.lua @@ -0,0 +1,7 @@ +tikz.within( '*' ) + +local l1 = line{ p{ 0, 0 }, p{ 2, 3 } } +local l2 = line{ p1 = p{ 0, 3 }, p2 = p{ 2, 1 } } + +draw{ l1 } +draw{ l2 } diff --git a/Master/texmf-dist/doc/latex/luatikz/example/lineb.lua b/Master/texmf-dist/doc/latex/luatikz/example/lineb.lua new file mode 100644 index 00000000000..0faf9049674 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/lineb.lua @@ -0,0 +1,9 @@ +tikz.within( '*' ) + +local l1 = line{ p{ 0, 0 }, p{ 2, 3 } } +local l2 = line{ p1 = p{ 0, 3 }, p2 = p{ 2, 1 } } +local pi = l1.intersectLine( l2 ) + +draw{ l1 } +draw{ l2 } +draw{ circle{ at = pi, radius = 0.1 } } diff --git a/Master/texmf-dist/doc/latex/luatikz/example/linec.lua b/Master/texmf-dist/doc/latex/luatikz/example/linec.lua new file mode 100644 index 00000000000..115def104b3 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/linec.lua @@ -0,0 +1,7 @@ +tikz.within( '*' ) + +draw{ line{ + p1 = p{ 0, 0 }, + phi = -math.pi / 4, + length = 2, +} } diff --git a/Master/texmf-dist/doc/latex/luatikz/example/lined.lua b/Master/texmf-dist/doc/latex/luatikz/example/lined.lua new file mode 100644 index 00000000000..38bc0eaa081 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/lined.lua @@ -0,0 +1,15 @@ +tikz.within( '*' ) + +local l = line{ p{ 0, 0 }, p{ 5, 0 } } +draw{ l } + +for i = 1, 10 +do + l = + line{ + p1 = l.p2, + phi = l.phi + math.pi / 5, + length = l.length * 2 / 3, + } + draw{ l } +end diff --git a/Master/texmf-dist/doc/latex/luatikz/example/nodea.lua b/Master/texmf-dist/doc/latex/luatikz/example/nodea.lua new file mode 100644 index 00000000000..4d34f2c0991 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/nodea.lua @@ -0,0 +1,12 @@ +tikz.within( '*' ) + +put{ + node{ + at = p{ 0, 0 }, + text = [[$a^2 + b^2 = c^2$]], + }, + node{ + at = p{ 2, 1 }, + text = [[$sin(\phi) = \frac{b}{a}$]], + } +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/nodeb.lua b/Master/texmf-dist/doc/latex/luatikz/example/nodeb.lua new file mode 100644 index 00000000000..85d8aeb49e1 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/nodeb.lua @@ -0,0 +1,18 @@ +tikz.within( '*' ) + +local r1 = + rect{ + pc = p{ 0, 0 }, + size = p{ 3, 3 }, + } + +draw{ r1 } + +put{ + node{ + at = r1.pc, + text = [[this is the center of a rect]], + text_width = '2cm', + rotate = 45, + }, +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/plota.lua b/Master/texmf-dist/doc/latex/luatikz/example/plota.lua new file mode 100644 index 00000000000..1a5721082ef --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/plota.lua @@ -0,0 +1,14 @@ +tikz.within( '*' ) + +draw{ + plot{ + at = p{ 0, 0 }, + from = 0, + to = 5, + step = 0.05, + func = + function( d ) + return p{ d, math.pow( d - 2.5, 2 ) / 2 } + end + } +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/polylinea.lua b/Master/texmf-dist/doc/latex/luatikz/example/polylinea.lua new file mode 100644 index 00000000000..f19954798a6 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/polylinea.lua @@ -0,0 +1,11 @@ +tikz.within( '*' ) + +draw{ + polyline{ + p{ 0, 0 }, + p{ 2, 2 }, + p{ 4, 0 }, + p{ 3, -1 }, + 'cycle', + } +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/radon1.lua b/Master/texmf-dist/doc/latex/luatikz/example/radon1.lua new file mode 100644 index 00000000000..166c44c7635 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/radon1.lua @@ -0,0 +1,119 @@ +tikz.within( '*' ) + +local cos = math.cos +local sin = math.sin +local pi = math.pi + +-- granularity of calculation +local fine = 10 + +-- factor the projection length is reduced +local fproj = 0.35 + +-- strength of the ellipse mediums +local s1 = 1.00 +local s2 = 1.50 +local s3 = 1.75 + +local e1 = ellipse{ at=p{ 0.00, 0.00 }, xradius=3.00, yradius=3.00 } +local e2 = ellipse{ at=p{ 0.40, 1.20 }, xradius=0.85, yradius=0.50 } +local e3 = ellipse{ at=p{ 0.00, -0.89 }, xradius=1.00, yradius=0.60 } + +draw{ fill='black!08!white', line_width=1, e1 } +draw{ fill='black!16!white', line_width=1, e2 } +draw{ fill='black!24!white', line_width=1, e3 } + +-- list of projection angles +local listphi = +{ + -1/4 * pi, + 2/4 * pi, + 5/4 * pi, +} + +-- length of projection lines +local lenmaintop = 5.0 +local lenmainbot = 6.5 + +for proji, phimain in ipairs( listphi ) +do + local lmain = + line{ + p{ cos( phimain ), sin( phimain ) } * -lenmaintop, + p{ cos( phimain ), sin( phimain ) } * lenmainbot, + } + local phinorm = phimain - pi/2 + + -- gets a point on the projection. + -- dp: distance from projection center + -- dv: projection value + function getpproj( dp, dv ) + return( + lmain.p2 + + p{ cos( phinorm ) * dp, sin( phinorm ) * dp } + + p{ cos( phimain ) * dv * fproj, sin( phimain ) * dv * fproj } + ) + end + + -- distance of projection line + local ddis = 1 / fine + + -- list of all projection points + local listp = { } + + for i = -3.5 * fine, 3.5 * fine + do + local p1i = + lmain.p1 + + p{ cos( phinorm ) * ddis * i, sin( phinorm ) * ddis * i } + local li = line{ p1i, p1i + ( lmain.p2 - lmain.p1 ) } + local lv = 0 + local is1 = e1.intersectLine( li ) + + if is1 and #is1 > 1 + then + local lis = line{ is1[ 1 ], is1[ 2 ] } + lv = lv + lis.length * s1 + end + + local is2 = e2.intersectLine( li ) + if is2 and #is2 > 1 + then + local lis = line{ is2[ 1 ], is2[ 2 ] } + lv = lv + lis.length * s2 + end + + local is3 = e3.intersectLine( li ) + if is3 and #is3 > 1 + then + local lis = line{ is3[ 1 ], is3[ 2 ] } + lv = lv + lis.length * s3 + end + + local pproj = getpproj( ddis * i, lv ) + if i % ( 0.7 * fine ) == 0 + then + draw{ + dotted, arrow, line_width=0.5, + line{ li.p1, getpproj( ddis * i, -0.20 ) }, + } + draw{ + dotted, line_width=0.5, + line{ li.p1, pproj }, + } + end + table.insert( listp, pproj ) + end + + -- draws the projection screen + local lenlproj = 8 + draw{ + line{ + getpproj( lenlproj / 2, 0 ), + getpproj( -lenlproj / 2, 0 ), + } + } + + -- draws the projection curve + draw{ line_width=1, polyline{ table.unpack( listp ) } } +end diff --git a/Master/texmf-dist/doc/latex/luatikz/example/recta.lua b/Master/texmf-dist/doc/latex/luatikz/example/recta.lua new file mode 100644 index 00000000000..91c8203ef78 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/recta.lua @@ -0,0 +1,21 @@ +tikz.within( '*' ) + +local r1 = + rect{ + pnw = p{ 0, 3 }, + pse = p{ 3, 0 }, + } + +local r2 = + rect{ + psw = r1.pse, + size = p{ 1, 1 }, + } + +local r3 = + rect{ + pc = r1.pc, + size = p{ 1.5, 1.5 }, + } + +draw{ r1, r2, r3 } diff --git a/Master/texmf-dist/doc/latex/luatikz/example/shadea.lua b/Master/texmf-dist/doc/latex/luatikz/example/shadea.lua new file mode 100644 index 00000000000..31e28dd3146 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/shadea.lua @@ -0,0 +1,9 @@ +tikz.within( '*' ) + +shade{ + ball_color = gray, + circle{ + at = p0, + radius = 2, + }, +} diff --git a/Master/texmf-dist/doc/latex/luatikz/example/sierpinski.lua b/Master/texmf-dist/doc/latex/luatikz/example/sierpinski.lua new file mode 100644 index 00000000000..0b5588bf918 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/sierpinski.lua @@ -0,0 +1,41 @@ +tikz.within( '*' ) + +local s60 = math.sin( 60 / 180 * math.pi ) +local c60 = math.cos( 60 / 180 * math.pi ) + +-- creates a table object having ptop, pleft and pright as points +-- and a "draw yourself" function +function equilateralTriangle( ptop, len ) + return { + ptop = ptop, + pleft = ptop + p{ -len/2, -len*s60 }, + pright = ptop + p{ len/2, -len*s60 }, + draw = + function( self ) + draw{ + fill = black, + draw = none, + polyline{ self.ptop, self.pleft, self.pright, 'cycle' } + } + end + } +end + +-- one step into the fractal +-- ptop: top point of triangle +-- len: current length +-- level: current fractal level +function drawFractal( ptop, len, level ) + if level == 1 + then + local t = equilateralTriangle( ptop, len ) + t:draw( ) + else + local ttop = equilateralTriangle( ptop, len / 2 ) + drawFractal( ttop.ptop, len / 2, level - 1 ) + drawFractal( ttop.pleft, len / 2, level - 1 ) + drawFractal( ttop.pright, len / 2, level - 1 ) + end +end + +drawFractal( p{ 0, 0 }, 8, 6 ) diff --git a/Master/texmf-dist/doc/latex/luatikz/example/spiral.lua b/Master/texmf-dist/doc/latex/luatikz/example/spiral.lua new file mode 100644 index 00000000000..12c135062ec --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/spiral.lua @@ -0,0 +1,16 @@ +tikz.within( '*' ) + +local pi = p{ 0, 0 } +local pdx = p{ 0.25, 0 } +local pdy = p{ 0, 0.25 } + +for k = 1, 20 +do + local sign = 1 + if k % 2 == 0 then sign = -1 end + local pn = pi + sign * k * pdx + local pn2 = pn + sign * k * pdy + draw{ line{ pi, pn }, line{ pn, pn2 } } + pi = pn2 +end + diff --git a/Master/texmf-dist/doc/latex/luatikz/example/stylea.lua b/Master/texmf-dist/doc/latex/luatikz/example/stylea.lua new file mode 100644 index 00000000000..ef3805cdd02 --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/stylea.lua @@ -0,0 +1,19 @@ +tikz.within( '*' ) + +local l1 = line{ p{ 0, 0 }, p{ 3, 1 } } +local l2 = line{ p{ 0, -1 }, p{ 3, 0 } } +local l3 = line{ p{ 0, -2 }, p{ 3, -1 } } + +draw{ arrow, l1 } +draw{ double_arrow, dashed, l2 } +draw{ color = purple, line_width = 2, dotted, l3 } + +put{ node{ + at = l3.pc, + anchor = center, + align = center, + color = purple, + rotate = l3.phi * 180 / math.pi, + text = 'label for purple line', + text_width = '2cm', +} } diff --git a/Master/texmf-dist/doc/latex/luatikz/example/superEllipse.lua b/Master/texmf-dist/doc/latex/luatikz/example/superEllipse.lua new file mode 100644 index 00000000000..32c629008ca --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/example/superEllipse.lua @@ -0,0 +1,22 @@ +tikz.within( '*' ) + +local list = { 1, 1.5, 2, 4, 999 } + +for i, v in ipairs( list ) +do + local pi = p{ ( i - 1 ) * 2.5, 0 } + draw{ + superEllipse{ + at = pi, + n = v, + xradius = 1, + yradius = 1, + } + } + put{ + node{ + at = pi, + text = 'n = ' .. v, + } + } +end diff --git a/Master/texmf-dist/doc/latex/luatikz/luatikz.pdf b/Master/texmf-dist/doc/latex/luatikz/luatikz.pdf Binary files differnew file mode 100644 index 00000000000..983105ad7fb --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/luatikz.pdf diff --git a/Master/texmf-dist/doc/latex/luatikz/luatikz.tex b/Master/texmf-dist/doc/latex/luatikz/luatikz.tex new file mode 100644 index 00000000000..d4bf734b1dd --- /dev/null +++ b/Master/texmf-dist/doc/latex/luatikz/luatikz.tex @@ -0,0 +1,204 @@ +\documentclass[a4paper,11pt]{ltxdoc} + +\usepackage[utf8]{inputenc} +\usepackage{makeidx}\makeindex +\usepackage{luatextra} +\usepackage[margin=1in]{geometry} + +\usepackage{fancyvrb} +\fvset{frame=single,numbers=left,numbersep=3pt,tabsize=4} + +\usepackage{tikz} +\usetikzlibrary{math,backgrounds,calc,intersections,arrows.meta,external,decorations.pathreplacing,shadings} +\directlua{dofile('./luatikz.lua')} + +\newcommand{\example}[2] +{ +\par#2 +\VerbatimInput{example/#1.lua} +{\centering +\begin{tikzpicture}[framed,scale=1] +\directlua{dofile('example/#1.lua')tikz.without()} +\end{tikzpicture}\par} +} + +\newcommand{\examplecode}[2] +{ +\bigskip\par\noindent #2 +\VerbatimInput{example/#1.lua} +} + + +\title{luatikz} +\author{Axel Kittenberger} +\def\version{2.12.0} +\date{luatikz version \version} + +\setlength{\parindent}{0pt} +\setlength{\parskip}{1ex} + +\begin{document} + +\maketitle + +\section{Introduction} +Luatikz is a graphics library to draw tikz graphics using the Lua programming language. + +\example{intro} +{Following code draws two lines by specifying begin and end points. First using intermediatery variables and the second line within a single codeline:} + +Following \TeX{} wrapper can be used to compile the luatikz Lua code. +\VerbatimInput{example/wrapper.tex} + +Luatikz obviously needs \LuaLaTeX{} to compile. + +Note that 2D graphics is a vast topic, functionality to luatikz has been and will be added on a per need basis. + +\section{Pointer math} + +Mathematical operations are possible with points, adding them with each other or multiplying them with a scalar. +\example{spiral}{This example uses pointer math to create a spiral:} + +\newpage +\section{Immutability} + +In luatikz pointers like all objects are immutable. That means a object once created in memory can no longer be changed. +However the variable holding an object can be changed to another object with different attributes. + +\examplecode{immute1}{Thus following example is invalid:} +\examplecode{immute2}{This on the other hand are two valid methods to change the value of p1} + +\newpage +\section{luatikz objects} + +\subsection{Bezier (quatratic)} +\example{bezier2}{A quadratic bezier curve is defined by it begin, end and a control point:} + +\newpage +\subsection{Bezier (cubic)} +\example{bezier3a}{A cubic bezier curve is defined by it begin, end and two control points:} + +\newpage +A cubic bezier has the functions pt and phit that return the point and angle ranging from 0..1 on the curve. +\example{bezier3b}{This example draw 10 normal lines onto the bezier curve:} + +\newpage +\subsection{BLine} +\example{blinea}{A bline is defined by it's begin and it's end. Additionally to the standard line it is bend} + +\newpage +\subsection{Circle} +\example{circle}{A circle is defined by it's center (``at'') and the circle ``radius'':} + +\newpage +\subsection{Curve} +\example{curvea}{A curve is defined by a list of points:} + +\newpage +\example{curveb}{A curve can cycle and has a changeable tension:} + +\newpage +\subsection{Ellipse} +\example{ellipse}{An ellipse is difined by it's center (``at'') and a x- and yradius:} + +\newpage +\subsection{EllipseArc} +\example{ellipseArc}{An ellipse arc is a an ellipse limited by it's ``from'' and ``to'' angle:} + +\newpage +\subsection{Line} +\example{linea}{A line is defined by it's begin and it's end. There are two basic variants to define a line:} + +\example{lineb}{You can use intersectLine() to find the intersection of a line with another. If there is none ``nil'' will be returned:} + +\newpage +\example{linec}{A line can also be defined by it's starting point, angle and length:} + +\example{lined}{``length'' and ``phi'' are attributes of a line:} + +\newpage +\subsection{Plot} +\example{plota}{A plot uses a function to determine a series of points on a curve. It takes values going ``from''--``to''. The function is to be a lua function that takes the input scalar and returns a point. The whole curve is offset ``at'' a point:} + +%\newpage +%\subsection{SuperEllipse} +%\example{superEllipse}{A ``super'' ellipse is just as an ellipse, but additionally has a strength factor ``n'' that ranges from diamond, to ellipse to rectangle:} + +\newpage +\subsection{Polyline} +\example{polylinea}{A polyline is a list of points to be connected via straight lines. If the string ``cycle'' is given at the end, it cycles:} + +\newpage +\subsection{Rect} +\example{recta}{Rectangles have various creation options. Also they provide a wide range of attributes of their points ``pnw'', ``pne'', ``psw'', ``pse'', ``pn'', ``pe'', ``ps'', ``pw'', ``pc'', ``height'', and ``width'': +} + +\newpage +\section{Labels a.k.a Nodes} + +Labels are created as nodes. Contrary to all other objects they do not need the ``draw'' command to be printed, but the ``put'' command. This is due any call to ``draw'' is turned into exactly one ``draw'' command to tikz and nodes in tikz are not using the ``draw'' command. + +\example{nodea}{In it's simplest form a node is specified by it's position and text. The double square brackets are Lua's way to make string constants that may contain simple blackslashes:} + +All constructors options of node are as follows; they correspond to the standard tikz options: +\begin{itemize} + \item above + \item anchor + \item align + \item at + \item below + \item color + \item draw + \item left + \item minimum\_height + \item node\_distance + \item name + \item right + \item rotate + \item text + \item text\_width +\end{itemize} +\newpage + +\example{nodeb}{Another node example} + +\newpage +\section{Styling} + +Styling is applied to draw commands by specifying style options, luatikz autodetects the difference between objects and styles. + +\example{stylea}{An example using arrows and dashes} + +\newpage +\section{Shades} + +The ``shade'' command works analogous to classical tikz. + +\example{shadea}{For example a ball:} + +Recognized shade options are: +\begin{itemize} + \item ball\_color + \item left\_color + \item lower\_left\_color + \item lower\_right\_color + \item opacity + \item right\_color + \item shading + \item upper\_left\_color + \item upper\_right\_color +\end{itemize} + +\newpage +\section{Some larger examples} + +\subsection{A radon projection} +\example{radon1}{A radon projection, calculating correct projection curves:} + +\newpage +\subsection{A sierpiński fractal} +\example{sierpinski}{A sierpiński fractal. This one creates own temporary lua objects:} + +\printindex + +\end{document} diff --git a/Master/texmf-dist/tex/latex/luatikz/luatikz.lua b/Master/texmf-dist/tex/latex/luatikz/luatikz.lua new file mode 100644 index 00000000000..1c18f2f6278 --- /dev/null +++ b/Master/texmf-dist/tex/latex/luatikz/luatikz.lua @@ -0,0 +1,1999 @@ +local _version = '2.12.0' + +if tikz +then + if tikz.version ~= _version + then + error( 'version chaos' ) + end + return +end + +tikz = { version = _version } + +--==========================================================================-- +-- DEFINES +--==========================================================================-- + +-- directions +tikz.north = 'north' +tikz.north_east = 'north east' +tikz.east = 'east' +tikz.south_east = 'south east' +tikz.south = 'south' +tikz.south_west = 'south west' +tikz.west = 'west' +tikz.north_west = 'north west' + +-- colors +tikz.black = 'black' +tikz.blue = 'blue' +tikz.brown = 'brown' +tikz.cyan = 'cyan' +tikz.darkgray = 'darkgray' +tikz.gray = 'gray' +tikz.green = 'green' +tikz.lightgray = 'lightgray' +tikz.lime = 'lime' +tikz.magenta = 'magenta' +tikz.olive = 'olive' +tikz.orange = 'orange' +tikz.pink = 'pink' +tikz.purple = 'purple' +tikz.red = 'red' +tikz.teal = 'teal' +tikz.violet = 'violet' +tikz.yellow = 'yellow' +tikz.white = 'white' + +-- align +tikz.center = 'center' +tikz.left = 'left' +tikz.right = 'right' + +tikz.none = 'none' + +-- line caps +tikz.round = 'round' + +--==========================================================================-- +-- HELPERS -- +--==========================================================================-- + +-- if defined writes output here +local outfile + +-- +-- Prints arguments to tex and to stdout. +-- +local function tprint( ... ) + local args = {...} + print( table.concat( args ) ) + + if tex + then + tex.print( table.concat( args ) ) + end + + if outfile + then + outfile:write( table.concat( args ) ) + outfile:write( '\n%%% DO NOT EDIT THIS FILE %%%\n' ) + end +end +tikz.tprint = tprint + +-- +-- Flattens an object stack. +-- +-- The content of all numerated unclassed objects +-- are put into a copy of obj. +-- +local function flatten( o ) + local r = { } + for _, v in ipairs( o ) + do + if type( v ) == 'table' and getmetatable( v ) == nil + then + local fv = flatten( v ) + for _, fvv in ipairs( fv ) + do + table.insert( r, fvv ) + end + for k, vv in pairs( fv ) + do + if type( k ) ~= 'number' + then + r[ k ] = vv + end + end + else + table.insert( r, v ) + end + end + -- copies (and overwrites) all named attributes + for k, v in pairs( o ) + do + if type( k ) ~= 'number' + then + r[ k ] = v + end + end + return r +end + +-- +-- A key marking an object having a zString function. +-- +local _zString = { } + +-- +-- Converts everything to a tikz string. +-- +local function zString( v ) + if type( v ) == 'table' and v[ _zString ] + then + return v[ _zString ]( v ) + end + return tostring( v ) +end + +-- +-- Creates an immutable class. +-- +local function immutable( definer ) + local def = { } + local lazy = { } + local proto = { } + def.lazy = lazy + def.proto = proto + definer( def ) -- the callee fills in data + local k = { } -- key the hidden table + + local mt = { } + mt.__index = + function( self, key ) + if key == 'id' then return def.id end + + -- first check if native value + local v = self[ k ][ key ] + if v then return v end + + -- then if a lazy function + local f = lazy[ key ] + if f + then + local v = f( self ) + self[ k ][ key ] = v -- cache + return v + end + + -- then if a proto value + v = proto[ key ] + if v + then + if type( v ) == 'function' + then + return( + function(...) + return v( self, table.unpack( {...} ) ) + end + ) + else + return v + end + end + + -- otherwise + -- error( 'invalid property' ) + end + + mt.__newindex = + function( ) + error( 'this is an immutable' ) + end + + if def.add + then + mt.__add = def.add + end + + if def.concat + then + mt.__concat = def.concat + end + + if def.div + then + mt.__div = def.div + end + + if def.mul + then + mt.__mul = def.mul + end + + if def.sub + then + mt.__sub = def.sub + end + + if def.tostring + then + mt.__tostring = def.tostring + end + + return function(...) + local args = {...} + local nt = def.constructor( table.unpack( args ) ) + local o = { [ k ] = nt, [ _zString ] = def.zString } + setmetatable( o, mt ) + return o + end +end +tikz.immutable = immutable + +-- +-- writes out direct options +-- +local function _opts( s, _opts, haveOpts ) + if not _opts + then + return haveOpts + end + + for k, v in pairs( _opts ) + do + if not haveOpts + then + table.insert( s, '[' ) + else + table.insert( s, ',' ) + end + haveOpts = true + if type( k ) == 'number' + then + table.insert( s, v ) + else + table.insert( s, k..'='..v ) + end + end + return haveOpts +end + +------------------------------------------------------------------------------- +-- Point. +------------------------------------------------------------------------------- +tikz.p = +immutable( function( def ) + def.id = 'point' + + def.add = + function( left, right ) + if right.id == 'line' + or right.id == 'bezier3' + then + return right + left + end + + return tikz.p{ left.x + right.x, left.y + right.y } + end + + def.concat = + function( left, right ) + return zString( left )..zString( right ) + end + + -- constructor + def.constructor = + function( args ) + return { x = args[ 1 ], y = args[ 2 ] } + end + + -- divisor + def.div = + function( left, right ) + return tikz.p{ left.x / right, left.y / right } + end + + def.mul = + function( left, right ) + if type( right ) == 'number' + then + return tikz.p{ left.x * right, left.y * right } + elseif type( left ) == 'number' + then + return tikz.p{ left * right.x, left * right.y } + elseif type( right ) == 'table' + then + if right.id == 'point' + then + return tikz.p{ left.x * right.x, left.y * right.y } + end + end + error( 'invalid operation' ) + end + + def.sub = + function( left, right ) + return tikz.p{ left.x - right.x, left.y - right.y } + end + + def.tostring = + function( self ) + return 'p{ '..self.x..', '..self.y..' }' + end + + -- converts to a tikz string. + def.zString = + function( self ) + return '('..self.x..','..self.y..')' + end +end ) + +------------------------------------------------------------------------------- +-- A full circle. +------------------------------------------------------------------------------- +tikz.circle = +immutable( function( def ) + def.id = 'circle' + + -- constructor + def.constructor = + function( args ) + return { + at = args.at, + radius = args.radius, + } + end + + -- converts to a tikz string. + def.zString = + function( self ) + return zString( self.at )..' circle ('.. self.radius .. ')' + end +end ) + +------------------------------------------------------------------------------- +-- A quadratic bezier curve. +------------------------------------------------------------------------------- +tikz.bezier2 = +immutable( function( def ) + def.id = 'bezier2' + + -- constructor + def.constructor = + function( args ) + local p1 = args.p1 + local pc = args.pc + local p2 = args.p2 + + return { + p1 = p1, + pc = pc, + p2 = p2, + } + end + + -- draws helping information + def.proto.drawHelpers = + function( self, prefix ) + tikz.draw{ draw = 'red', tikz.line{ self.p1, self.pc } } + tikz.draw{ draw = 'blue', tikz.line{ self.pc, self.p2 } } + if prefix ~= nil + then + tikz.put{ tikz.node{ + at = self.p1, + anchor = 'north west', + text = prefix .. '1', + } } + tikz.put{ tikz.node{ + at = self.pc, + anchor = 'north west', + text = prefix .. 'c', + } } + tikz.put{ tikz.node{ + at = self.p2, + anchor = 'north west', + text = prefix .. '2', + } } + end + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { } + table.insert( s, zString( self.p1 ) ) + table.insert( s, '.. controls' ) + table.insert( s, zString( self.pc ) ) + table.insert( s, '..' ) + table.insert( s, zString( self.p2 ) ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- A cubic bezier curve. +------------------------------------------------------------------------------- +tikz.bezier3 = +immutable( function( def ) + def.id = 'bezier3' + + def.add = + function( left, right ) + if right.id == 'point' + then + return tikz.bezier3{ + p1 = left.p1 + right, + pc1 = left.pc1 + right, + pc2 = left.pc2 + right, + p2 = left.p2 + right, + } + end + error( 'unknown operation' ) + end + + -- constructor + def.constructor = + function( args ) + local p1 = args.p1 + local pc1 = args.pc1 + local pc2 = args.pc2 + local p2 = args.p2 + + return { + p1 = p1, + pc1 = pc1, + pc2 = pc2, + p2 = p2, + } + end + + -- draws helping information + def.proto.drawHelpers = + function( self, prefix ) + tikz.draw{ draw = 'red', tikz.line{ self.p1, self.pc1 } } + tikz.draw{ draw = 'yellow', tikz.line{ self.pc1, self.pc2 } } + tikz.draw{ draw = 'blue', tikz.line{ self.pc2, self.p2 } } + if prefix ~= nil + then + tikz.put{ tikz.node{ + at = self.p1, + anchor = 'north west', + text = prefix .. '1', + } } + tikz.put{ tikz.node{ + at = self.pc1, + anchor = 'north west', + text = prefix .. 'c1', + } } + tikz.put{ tikz.node{ + at = self.pc2, + anchor = 'north west', + text = prefix .. 'c2', + } } + tikz.put{ tikz.node{ + at = self.p2, + anchor = 'north west', + text = prefix .. '2', + } } + end + end + + def.mul = + function( left, right ) + if type( right ) == 'number' + then + return tikz.bezier3 { + p1 = left.p1 * right, + pc1 = left.pc1 * right, + pc2 = left.pc2 * right, + p2 = left.p2 * right, + } + elseif type( left ) == 'number' + then + return tikz.bezier3 { + p1 = right.p1 * left, + pc1 = right.pc1 * left, + pc2 = right.pc2 * left, + p2 = right.p2 * left, + } + else + error( 'invalid operation' ) + end + end + + -- point in center + def.lazy.pc = + function( self ) + return self.pt( 0.5 ) + end + + -- gets angle at t (0-1) + def.proto.phit = + function( self, t ) + local p1 = self.p1 + local pc1 = self.pc1 + local pc2 = self.pc2 + local p2 = self.p2 + + local u = 1 - t + local uu3 = 3 * u * u + local ut6 = 6 * u * t + local tt3 = 3 * t * t + + return math.atan2( + -uu3 * p1.y + uu3 * pc1.y - ut6 * pc1.y + ut6 * pc2.y - tt3 * pc2.y + tt3 * p2.y, + -uu3 * p1.x + uu3 * pc1.x - ut6 * pc1.x + ut6 * pc2.x - tt3 * pc2.x + tt3 * p2.x + ) + end + + -- reverts p1 and p2 and pc1 and pc2 respectively + def.lazy.revert = + function( self ) + return tikz.bezier3{ + p1 = self.p2, + pc1 = self.pc2, + pc2 = self.pc1, + p2 = self.p1, + } + end + + -- gets point at t (0-1) + def.proto.pt = + function( self, t ) + if type( t ) ~= 'number' or t < 0 or t > 1 + then + error( 'invalid pt' ) + end + + local p1 = self.p1 + local pc1 = self.pc1 + local pc2 = self.pc2 + local p2 = self.p2 + local t1 = 1 - t + + return( + tikz.p{ + t1^3*p1.x + 3*t*t1^2*pc1.x + 3 *t^2*t1*pc2.x + t^3*p2.x, + t1^3*p1.y + 3*t*t1^2*pc1.y + 3 *t^2*t1*pc2.y + t^3*p2.y + } + ) + end + + def.sub = + function( left, right ) + if right.id == 'point' + then + return tikz.bezier3{ + p1 = left.p1 - right, + pc1 = left.pc1 - right, + pc2 = left.pc2 - right, + p2 = left.p2 - right, + } + end + error( 'unknown operation' ) + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { } + table.insert( s, zString( self.p1 ) ) + table.insert( s, '.. controls' ) + table.insert( s, zString( self.pc1 ) ) + table.insert( s, 'and' ) + table.insert( s, zString( self.pc2 ) ) + table.insert( s, '..' ) + table.insert( s, zString( self.p2 ) ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- A bend line +------------------------------------------------------------------------------- +tikz.bline = +immutable( function( def ) + def.id = 'bline' + + -- moves the line. + def.add = + function( left, right ) + if right.id == 'point' + then + return tikz.line{ p1 = left.p1 + right, p2 = left.p2 + right } + end + error( 'unknown operation' ) + end + + -- constructor + -- + -- either + -- { p1, p2 }, (a list ) + -- { p1 = ..., p2 = ... }, + -- { pc = ..., phi = ..., length = ... }, + def.constructor = + function( args ) + local p1 + local p2 + + if #args > 1 + then + -- list + p1 = args[ 1 ] + p2 = args[ 2 ] + elseif type( args.p1 ) ~= 'nil' and type( args.p2 ) ~= 'nil' + then + p1 = args.p1 + p2 = args.p2 + elseif args.phi ~= nil + then + local phi = args.phi + if args.pc ~= nil + then + if args.p1 ~= nil + or args.p2 ~= nil + then + error( 'invalid line options', 2 ) + end + local pc = args.pc + local len05 = args.length / 2 + p1 = pc + tikz.p{ math.cos( phi ), math.sin( phi ) } * len05 + p2 = pc - tikz.p{ math.cos( phi ), math.sin( phi ) } * len05 + elseif type( args.p1 ) ~= 'nil' + then + if args.pc ~= nil + or args.p2 ~= nil + then + error( 'invalid line options', 2 ) + end + p1 = args.p1 + p2 = p1 + tikz.p{ math.cos( phi ), math.sin( phi ) } * args.length + else + error( 'invalid line options', 2 ) + end + else + error( 'invalid line options', 2 ) + end + + return { + bend_left = args.bend_left, + bend_right = args.bend_right, + p1 = p1, + p2 = p2, + } + end + + -- converts to a cubic bezier (that should look the same) + def.lazy.bezier3 = + function( self ) + local phi + if self.bend_right ~= nil then + phi = self.bend_right * math.pi / 180 + else + phi = -self.bend_left * math.pi / 180 + end + local line = self.line + local phil = line.phi + local len = line.length * 0.3915 + local lt1 = + tikz.line{ + p1 = line.p1, + phi = phil-phi, + length = len + } + local lt2 = + tikz.line{ + p1 = line.p2, + phi = phil+phi+math.pi, + length = len + } + + return tikz.bezier3{ + p1 = line.p1, + pc1 = lt1.p2, + pc2 = lt2.p2, + p2 = line.p2, + } + end + + -- converts to a straight line. + def.lazy.line = + function( self ) + return tikz.line{ + p1 = self.p1, + p2 = self.p2, + } + end + + -- point in center + def.lazy.pc = + function( self ) + return self.bezier3.pc + end + + -- gets point at t (0-1). + def.proto.pt = + function( self, t ) + return self.bezier3.pt( t ) + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { } + table.insert( s, zString( self.p1 ) ) + table.insert( s, 'to' ) + if self.bend_left ~= nil + then + table.insert( s, '[bend left='..self.bend_left..']' ) + end + if self.bend_right ~= nil + then + table.insert( s, '[bend right='..self.bend_right..']' ) + end + table.insert( s, zString( self.p2 ) ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- A curve is defined by a list of points. +------------------------------------------------------------------------------- +curve = +immutable( function( def ) + def.id = 'curve' + + -- constructor + def.constructor = + function( args ) + return { + points = args.points, + tension = args.tension, + cycle = args.cycle, + } + end + + -- draws helping information + def.proto.drawHelpers = + function( self, prefix ) + local points = self.points + for i, pi in ipairs( points ) + do + tikz.draw{ + fill = 'black', + tikz.circle{ + at = pi, + radius = 0.05, + } + } + if prefix ~= nil + then + tikz.put{ tikz.node{ + at = pi, + anchor = 'north west', + text = prefix .. i, + } } + end + end + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { 'plot' } + table.insert( s, '[' ) + if self.cycle + then + table.insert( s, 'smooth cycle' ) + else + table.insert( s, 'smooth' ) + end + if self.tension then + table.insert( s, ',tension='..self.tension ) + end + table.insert( s, ']' ) + local points = self.points + table.insert( s, 'coordinates' ) + table.insert( s, '{' ) + for _, p in ipairs( points ) + do + table.insert( s, zString( p ) ) + end + table.insert( s, '}' ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- A full ellipse. +------------------------------------------------------------------------------- +tikz.ellipse = +immutable( function( def ) + def.id = 'ellipse' + + -- constructor + def.constructor = + function( args ) + local at = args.at + local xradius = args.xradius + local yradius = args.yradius + + return { + at = at, + xradius = xradius, + yradius = yradius, + } + end + + -- intersect with a line. + def.proto.intersectLine = + function( self, line ) + local at = self.at + local rx = self.xradius + local ry = self.yradius + local p1 = line.p1 + local p2 = line.p2 + + local x0 = p1.x + local y0 = p1.y + local x1 = p2.x + local y1 = p2.y + local cx = at.x + local cy = at.y + + x0 = x0 - cx + y0 = y0 - cy + x1 = x1 - cx + y1 = y1 - cy + + local A = ((x1 - x0) * (x1 - x0)) / rx / rx + ((y1 - y0) * (y1 - y0)) / ry / ry + local B = (2 * x0 * (x1 - x0)) / rx / rx + (2 * y0 * (y1 - y0)) / ry / ry + local C = (x0 * x0) / rx / rx + (y0 * y0) / ry / ry - 1 + local D = B * B - 4 * A * C + + local tv = { } + if D == 0 + then + table.insert( tv, -B / 2 / A ) + else + table.insert( tv, (-B + math.sqrt(D)) / 2 / A ) + table.insert( tv, (-B - math.sqrt(D)) / 2 / A ) + end + + local r = { } + for _, t in ipairs( tv ) + do + if t >= 0 and t <= 1 + then + table.insert( + r, + p1 + tikz.p{ t * line.length * math.cos( line.phi ), t * line.length * math.sin( line.phi ) } + ) + end + end + + if #r == 0 + then + return + elseif #r == 1 + then + return r[ 1 ] + else + return r + end + end + + -- converts to a tikz string. + def.zString = + function( self ) + s = { } + table.insert( s, zString( self.at ) ) + table.insert( s, 'ellipse' ) + table.insert( s, '[' ) + table.insert( s, 'x radius =' ) + table.insert( s, zString( self.xradius ) ) + table.insert( s, ', y radius =' ) + table.insert( s, zString( self.yradius ) ) + table.insert( s, ']' ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- An ellipse part. +------------------------------------------------------------------------------- +tikz.ellipseArc = +immutable( function( def ) + def.id = 'ellipseArc' + + -- constructor + def.constructor = + function( args ) + return { + at = args.at, + from = args.from, + to = args.to, + xradius = args.xradius, + yradius = args.yradius, + } + end + + -- converts to a tikz string. + def.zString = + function( self ) + s = { } + table.insert( s, 'plot' ) + table.insert( s, '[domain =' ) + table.insert( s, self.from ) + table.insert( s, ':' ) + table.insert( s, self.to ) + table.insert( s, ',variable = \\phi,smooth]' ) + table.insert( s, + '({ '..zString(self.at.x)..'+'..zString(self.xradius)..'*cos(\\phi)},' + ..'{ '..zString(self.at.y)..'+'..zString(self.yradius)..'*sin(\\phi)})' + ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- Single line (segment). +------------------------------------------------------------------------------- +tikz.line = +immutable( function( def ) + def.id = 'line' + + -- moves the line. + def.add = + function( left, right ) + if right.id == 'point' + then + return tikz.line{ + p1 = left.p1 + right, + p2 = left.p2 + right, + } + end + error( 'unknown operation' ) + end + + -- multiplicator + def.mul = + function( left, right ) + if type( left ) == 'number' + then + return tikz.line{ + p1 = right.p1 * left, + p2 = right.p2 * left, + } + elseif type( right ) == 'number' + then + return tikz.line{ + p1 = left.p1 * right, + p2 = left.p2 * right, + } + end + error( 'unknown operation' ) + end + + -- constructor + -- + -- either + -- { p1, p2 }, (a list ) + -- { p1 = ..., p2 = ... }, + -- { pc = ..., phi = ..., length = ... }, + def.constructor = + function( args ) + local p1 + local p2 + + if #args > 1 + then + -- list + p1 = args[ 1 ] + p2 = args[ 2 ] + elseif type( args.p1 ) ~= 'nil' and type( args.p2 ) ~= 'nil' + then + p1 = args.p1 + p2 = args.p2 + elseif args.phi ~= nil + then + local phi = args.phi + if args.pc ~= nil + then + if args.p1 ~= nil + or args.p2 ~= nil + then + error( 'invalid line options', 2 ) + end + local pc = args.pc + local len05 = args.length / 2 + p1 = pc + tikz.p{ math.cos( phi ), math.sin( phi ) } * len05 + p2 = pc - tikz.p{ math.cos( phi ), math.sin( phi ) } * len05 + elseif type( args.p1 ) ~= 'nil' + then + if args.pc ~= nil + or args.p2 ~= nil + then + error( 'invalid line options', 2 ) + end + p1 = args.p1 + p2 = p1 + tikz.p{ math.cos( phi ), math.sin( phi ) } * args.length + else + error( 'invalid line options', 2 ) + end + else + error( 'invalid line options', 2 ) + end + + return { + p1 = p1, + p2 = p2, + } + end + + -- divisor + def.div = + function( left, right ) + if type( right ) == 'number' + then + return tikz.line{ + p1 = left.p1 / right, + p2 = left.p2 / right, + } + end + error( 'unknown operation' ) + end + + -- length of line. + def.lazy.length = + function( self ) + local p1 = self.p1 + local p2 = self.p2 + local dx = p2.x - p1.x + local dy = p2.y - p1.y + local result = math.sqrt( dx*dx + dy*dy ) + return result + end + + -- center of line. + def.lazy.pc = + function( self ) + local p1 = self.p1 + local p2 = self.p2 + local result = tikz.p{ ( p1.x + p2.x ) / 2, ( p1.y + p2.y ) / 2 } + return result + end + + -- angle of line. + def.lazy.phi = + function( self ) + local p1 = self.p1 + local p2 = self.p2 + local result = math.atan2( p2.y - p1.y, p2.x - p1.x ) + return result + end + + -- gets point at t (0-1). + def.proto.pt = + function( self, t ) + if type( t ) ~= 'number' or t < 0 or t > 1 + then + error( 'invalid pt' ) + end + + local p1 = self.p1 + local p2 = self.p2 + local phi = self.phi + local lt = self.length * t + + return( + tikz.p{ + p1.x + lt * math.cos( phi ), + p1.y + lt * math.sin( phi ), + } + ) + end + + -- intersects the line with another. + def.proto.intersectLine = + function( self, line ) + local p1 = self.p1 + local p2 = self.p2 + local p3 = line.p1 + local p4 = line.p2 + + if p1.x == p3.x and p1.y == p3.y then return p1 end + if p1.x == p4.x and p1.y == p4.y then return p1 end + if p2.x == p3.x and p2.y == p3.y then return p2 end + if p2.x == p4.x and p2.y == p4.y then return p2 end + + local den = ( p1.x - p2.x )*( p3.y - p4.y ) - ( p1.y - p2.y )*( p3.x - p4.x ); + if den == 0 + then + -- doesn't intersect + return + end + + local a = p1.x*p2.y - p1.y*p2.x; + local b = p3.x*p4.y - p3.y*p4.x; + local x = ( a*( p3.x - p4.x ) - ( p1.x - p2.x )*b ) / den; + local y = ( a*( p3.y - p4.y ) - ( p1.y - p2.y )*b ) / den; + + if + ( + ( x >= p1.x and x <= p2.x or x <= p1.x and x >= p2.x ) + and ( x >= p3.x and x <= p4.x or x <= p3.x and x >= p4.x ) + ) + or + ( + ( y >= p1.y and y <= p2.y or y <= p1.y and y >= p2.y ) + and ( y >= p3.y and y <= p4.y or y <= p3.y and y >= p4.y ) + ) + then + return tikz.p{ x, y } + end + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { } + table.insert( s, zString( self.p1 ) ) + table.insert( s, '--' ) + table.insert( s, zString( self.p2 ) ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- Function plot. +------------------------------------------------------------------------------- +tikz.plot = +immutable( function( def ) + def.id = 'plot' + + -- constructor + def.constructor = + function( args ) + return { + at = args.at, + from = args.from, + to = args.to, + step = args.step, + tension = args.tension, + func = args.func, + } + end + + def.lazy.points = + function( self ) + local from = self.from + local to = self.to + local step = self.step + if step == nil + then + step = ( to - from ) / 100 + end + local points = { } + local d + local at = self.at or tikz.p0 + for d = from, to, step + do + table.insert( points, at + self.func( d ) ) + end + return points + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { 'plot' } + table.insert( s, '[' ) + table.insert( s, 'smooth' ) + if self.tension + then + table.insert( s, ',tension='..self.tension ) + end + table.insert( s, ']' ) + + local points = self.points + + table.insert( s, 'coordinates' ) + table.insert( s, '{' ) + for _, p in ipairs( points ) + do + table.insert( s, zString( p ) ) + end + table.insert( s, '}' ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- A superEllipse +------------------------------------------------------------------------------- +tikz.superEllipse = +immutable( function( def ) + def.id = 'superEllipse' + + -- constructor + def.constructor = + function( args ) + local at = args.at + local n = args.n + local xradius = args.xradius + local yradius = args.yradius + + return { + at = at, + n = n, + xradius = xradius, + yradius = yradius, + } + end + + -- returns p on degree (0-360) + def.proto.pdeg = + function( self, t ) + if type( t ) ~= 'number' or t < 0 or t > 360 + then + error( 'invalid pdeg' ) + end + + local at = self.at + local n = self.n + local xo = self.xradius * math.abs( math.cos( t * math.pi / 180 ) )^(2/n) + local yo = self.yradius * math.abs( math.sin( t * math.pi / 180 ) )^(2/n) + + if t <= 90 + then + return tikz.p{ at.x + xo, at.y + yo } + elseif t <= 180 + then + return tikz.p{ at.x - xo, at.y + yo } + elseif t <= 270 + then + return tikz.p{ at.x - xo, at.y - yo } + else + return tikz.p{ at.x + xo, at.y - yo } + end + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { } + local at = self.at + local xa = at.x + local ya = at.y + local n = self.n + local xr = self.xradius + local yr = self.yradius + table.insert( s, 'plot[domain=0:90,variable=\\t,smooth]' ) + table.insert( s, '({'..xr..'*cos(\\t)^(2/'..n..')+'..xa..'},{'..yr..'*sin(\\t)^(2/'..n..')+'..ya..'})' ) + table.insert( s, '--' ) + table.insert( s, 'plot[domain=90:0,variable=\\t,smooth]' ) + table.insert( s, '({-'..xr..'*cos(\\t)^(2/'..n..')+'..xa..'},{'..yr..'*sin(\\t)^(2/'..n..')+'..ya..'})' ) + table.insert( s, '--' ) + table.insert( s, 'plot[domain=0:90,variable=\\t,smooth]' ) + table.insert( s, '({-'..xr..'*cos(\\t)^(2/'..n..')+'..xa..'},{-'..yr..'*sin(\\t)^(2/'..n..')+'..ya..'})' ) + table.insert( s, '--' ) + table.insert( s, 'plot[domain=90:0,variable=\\t,smooth]' ) + table.insert( s, '({'..xr..'*cos(\\t)^(2/'..n..')+'..xa..'},{-'..yr..'*sin(\\t)^(2/'..n..')+'..ya..'})' ) + table.insert( s, '-- cycle' ) + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- A reference to a named node. +------------------------------------------------------------------------------- +local optionsNamed = +{ + ref = false, + xshift = 'xshift', + yshift = 'yshift', +} + +tikz.named = +immutable( function( def ) + def.id = 'named' + + -- constructor + def.constructor = + function( args ) + local s = { } + _doOptions( s, args, optionsNamed, false, 2 ) + return { + opts = table.concat( s, ' ' ), + ref = args.ref, + } + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { } + table.insert( s, '(' ) + if self.opts + then + table.insert( s, self.opts ) + end + table.insert( s, self.ref ) + table.insert( s, ')' ) + return table.concat( s ) + end +end ) + +------------------------------------------------------------------------------- +-- Multiple connected lines. +------------------------------------------------------------------------------- +tikz.polyline = +immutable( function( def ) + def.id = 'polyline' + + -- constructor + def.constructor = + function( args ) + local o = { } + for _, v in ipairs( args ) + do + table.insert( o, v ) + end + return o + end + + -- converts to a tikz string. + def.zString = + function( self ) + local s = { '' } + for k, v in ipairs( self ) + do + if k > 1 then table.insert( s, '--' ) end + table.insert( s, zString( v ) ) + end + return table.concat( s, ' ' ) + end +end ) + +------------------------------------------------------------------------------- +-- A rectangle +------------------------------------------------------------------------------- +tikz.rect = +immutable( function( def ) + def.id = 'rect' + + -- constructor + def.constructor = + function( args ) + local psw + local pne + + if args.pnw ~= nil + then + if args.pse ~= nil + then + psw = tikz.p{ args.pnw.x, args.pse.y } + pne = tikz.p{ args.pse.x, args.pnw.y } + elseif args.size ~= nil + then + psw = tikz.p{ args.pnw.x, args.pnw.y - args.size.y } + pne = tikz.p{ args.pnw.x + args.size.x, args.pnw.y } + else + error( 'invalid rect options', 2 ) + end + elseif args.psw ~= nil + then + psw = args.psw + if args.pne ~= nil + then + pne = args.pne + elseif args.size ~= nil + then + pne = psw + args.size + else + error( 'invalid rect options', 2 ) + end + elseif args.pse ~= nil + then + if args.size ~= nil + then + psw = tikz.p{ args.pse.x - args.size.x, args.pse.y } + pne = tikz.p{ args.pse.x, args.pse.y + args.size.y } + else + error( 'invalid rect options', 2 ) + end + elseif args.pc ~= nil + then + if args.size ~= nil + then + psw = tikz.p{ args.pc.x - args.size.x / 2, args.pc.y - args.size.y / 2 } + pne = tikz.p{ args.pc.x + args.size.x / 2, args.pc.y + args.size.y / 2 } + else + error( 'invalid rect options', 2 ) + end + else + error( 'invalid rect options', 2 ) + end + + return { + psw = psw, + pne = pne, + } + end + + def.zString = + function( self ) + local s = { } + table.insert( s, zString( self.psw ) ) + table.insert( s, 'rectangle' ) + table.insert( s, zString( self.pne ) ) + return table.concat( s, ' ' ) + end + + def.lazy.e = + function( self ) + return self.pne.x + end + + def.lazy.height = + function( self ) + return self.pne.y - self.psw.y + end + + def.lazy.n = + function( self ) + return self.pne.y + end + + def.lazy.pc = + function( self ) + return tikz.p{ self.psw.x + self.width / 2, self.psw.y + self.height / 2 } + end + + def.lazy.pe = + function( self ) + return tikz.p{ self.pne.x, self.psw.y + self.height / 2 } + end + + def.lazy.pn = + function( self ) + return tikz.p{ self.psw.x + self.width / 2, self.pne.y } + end + + def.lazy.pnw = + function( self ) + return tikz.p{ self.psw.x, self.pne.y } + end + + def.lazy.ps = + function( self ) + return tikz.p{ self.psw.x + self.width / 2, self.psw.y } + end + + def.lazy.pse = + function( self ) + return tikz.p{ self.pne.x, self.psw.y } + end + + def.lazy.pw = + function( self ) + return tikz.p{ self.psw.x, self.psw.y + self.height / 2 } + end + + def.lazy.s = + function( self ) + return self.psw.y + end + + def.lazy.size = + function( self ) + return tikz.p{ self.width, self.height } + end + + def.lazy.w = + function( self ) + return self.psw.x + end + + def.lazy.width = + function( self ) + return self.pne.x - self.psw.x + end +end ) + + +--==========================================================================-- +-- STYLES -- +--==========================================================================-- +tikz.style = +immutable( function( def ) + def.id = 'style' + + -- constructor + def.constructor = + function( name ) + return { name=name } + end +end ) + +tikz.above = tikz.style( 'above' ) +tikz.arrow = tikz.style( '-{Latex}' ) +tikz.below = tikz.style( 'below' ) +tikz.dashed = tikz.style( 'dashed' ) +tikz.dotted = tikz.style( 'dotted' ) +tikz.double_arrow = tikz.style( '{Latex}-{Latex}' ) +tikz.even_odd_rule = tikz.style( 'even odd rule' ) +tikz.midway = tikz.style( 'midway' ) + +--==========================================================================-- +-- OUTPUT --- +--==========================================================================-- + +-- +-- Writes out a named option. +-- +-- ~s: string to build +-- ~args: arguments +-- ~name: name of option +-- ~haveOpts: true if had options +-- ~rename: if defined rename options on output +-- +local function optionNamed( s, args, name, haveOpts, rename ) + + local v = args[ name ] + + if not v + then + return haveOpts + end + + if not rename + then + return haveOpts + end + + if not haveOpts + then + table.insert( s, '[' ) + else + table.insert( s, ',' ) + end + + if v == true + then + table.insert( s, rename ) + else + table.insert( s, rename..'='..v ) + end + + return true +end + +-- +-- Writes out an unnamed option. +-- +-- ~s: string to build +-- ~name: name of option +-- ~haveOpts: true if had options +-- +local function unnamedOption( s, name, haveOpts ) + if not haveOpts + then + table.insert( s, '[' ) + else + table.insert( s, ',' ) + end + table.insert( s, name ) + return true +end + +-- +-- Custom key compare. +-- +-- keys to put on top +local topKeys = +{ + node_distance = true, +} + +local function kcompare( ka, kb ) + local ta = topKeys[ ka ] + local tb = topKeys[ kb ] + if ta and not tb then return true end + if not ta and tb then return false end + return ka < kb +end + +-- +-- A helper to parse arguments to pass as drawing options to hand to tikz. +-- +-- s: string to build +-- args: the arguments to parse. +-- opts: named options to pass on +-- haveOpts: true [ has already been built +-- level: call level for error throwing +-- +local function _doOptions( s, args, opts, haveOpts, level ) + args = flatten( args ) + + for _, v in ipairs( args ) + do + if v.id == 'style' + then + haveOpts = unnamedOption( s, v.name, haveOpts ) + end + end + + local nkeys = { } + for key in pairs( args ) + do + if type( key ) ~= 'number' + then + table.insert( nkeys, key ) + end + end + table.sort( nkeys, kcompare ) + + for _, k in ipairs( nkeys ) + do + local ok = opts[ k ] + if ok + then + haveOpts = optionNamed( s, args, k, haveOpts, ok ) + elseif ok == nil + then + error( 'unknown option '..k, level + 1 ) + end + end + + haveOpts = _opts( s, args._opts, haveOpts ) + + if haveOpts + then + table.insert( s, ']' ) + end +end + +------------------------------------------------------------------------------- +-- Drawing shapes. +------------------------------------------------------------------------------- +local optionsDraw = +{ + decorate = 'decorate', + decoration = 'decoration', + dash_pattern = 'dash pattern', + color = 'color', + draw = 'draw', + fill = 'fill', + line_cap = 'line cap', + line_width = 'line width', + opacity = 'opacity', + pattern = 'pattern', + rotate = 'rotate', + transform_canvas = 'transform canvas', + xshift = 'xshift', + yshift = 'yshift', + _butt_cap = '-Butt Cap', + butt_cap_ = 'Butt Cap-', + _round_cap = '-{Round Cap[]}', + round_cap_ = '{Round Cap[]}-', + _round_cap_ = '{Round Cap[]}-{Round Cap[]}', +} + +-- +-- Puts out a bounding box command +-- +tikz.boundingbox = +function( args ) + tprint( '\\pgfresetboundingbox' ) + local s = { '\\path [use as bounding box] ' } + for _, v in ipairs( args ) + do + if v.id ~= 'style' + then + table.insert( s, zString( v ) ) + end + end + table.insert( s, ';' ) + tprint( table.unpack( s ) ) +end + +-- +-- Puts out a draw command. +-- +tikz.draw = +function( args ) + local s = { '\\draw ' } + _doOptions( s, args, optionsDraw, false, 2 ) + + for _, v in ipairs( args ) + do + if v.id ~= 'style' + then + table.insert( s, zString( v ) ) + end + end + + table.insert( s, ';' ) + tprint( table.unpack( s ) ) +end + +-- +-- Puts out a path command. +-- +tikz.path = +function( args ) + local s = { '\\path' } + _doOptions( s, args, optionsDraw, false, 2 ) + + for _, v in ipairs( args ) + do + if v.id ~= 'style' + then + table.insert( s, zString( v ) ) + end + end + table.insert( s, ';' ) + tprint( table.unpack( s ) ) +end + +-- +-- Puts out a bounding box. +-- +tikz.clip = +function( args ) + local s = { '\\begin{pgfinterruptboundingbox}', '\\clip' } + _doOptions( s, args, optionsDraw, false, 2 ) + + for _, v in ipairs( args ) + do + if v.id ~= 'style' then table.insert( s, zString( v ) ) end + end + table.insert( s, ';' ) + table.insert( s, '\\end{pgfinterruptboundingbox}' ) + tprint( table.unpack( s ) ) +end + +local shadeOptions = +{ + ball_color = 'ball color', + left_color = 'left color', + lower_left_color = 'lower left', + lower_right_color = 'lower right', + opacity = 'opacity', + right_color = 'right color', + shading = 'shading', + upper_left_color = 'upper left', + upper_right_color = 'upper right', +} + +-- +-- Puts out a shade command. +-- +tikz.shade = +function( args ) + local s = { '\\shade' } + _doOptions( s, args, shadeOptions, false, 2 ) + + for _, v in ipairs( args ) + do + if v.id ~= 'style' then table.insert( s, zString( v ) ) end + end + table.insert( s, ';' ) + tprint( table.unpack( s ) ) +end + +-- +-- Puts out z stuff. +-- +tikz.put = +function( args ) + for _, v in ipairs( args ) + do + local s = { } + if v.id == 'node' + then + table.insert( s, '\\' ) + table.insert( s, zString( v ) ) + table.insert( s, ';' ) + else + error( 'unknown: ' .. v.id, 1 ) + end + tprint( table.unpack( s ) ) + end +end + +tikz.declarehorizonalshading = +function( args ) + local steps = args.steps + local name = args.name + local s = { '\\pgfdeclarehorizontalshading{' .. name .. '}{100bp}{' } + + local keys = { } + for k, _ in pairs( steps ) + do + table.insert( keys, k ) + end + + table.sort( keys ) + for _, k in ipairs( keys ) + do + if _ > 1 then table.insert( s, ';' ) end + table.insert( s, 'color(' .. k .. 'bp)=(' .. steps[ k ] .. ')' ) + end + table.insert( s, '}' ) + + tprint( table.unpack( s ) ) +end + +------------------------------------------------------------------------------- +-- A node to be defined to tikZ +------------------------------------------------------------------------------- +local optionsNode = +{ + above = 'above', + anchor = 'anchor', + align = 'align', + at = false, + below = 'below', + color = 'color', + draw = 'draw', + left = 'left', + minimum_height = 'minimum height', + node_distance = 'node distance', + name = false, + right = 'right', + rotate = 'rotate', + text = false, + text_width = 'text width', +} + +tikz.node = +immutable( function( def ) + def.id = 'node'; + + def.zString = + function( self ) + local s = { 'node' } + + table.insert( s, self.opts ) + if self.name + then + table.insert( s, ' (' ) + table.insert( s, self.name ) + table.insert( s, ')' ) + end + + if self.at + then + table.insert( s, ' at ' ) + table.insert( s, zString( self.at ) ) + end + + if self.text + then + table.insert( s, ' {' ) + local text = string.gsub( self.text, '\n', '' ) + table.insert( s, text ) + table.insert( s, '}' ) + end + + return table.concat( s ) + end + + -- constructor + def.constructor = + function( args ) + local s = { } + _doOptions( s, args, optionsNode, false, 2 ) + return { + at = args.at, + name = args.name, + opts = table.concat( s, ' ' ), + text = args.text + } + end +end ) + +tikz.outfile = +function( filename ) + outfile = io.open( filename, 'w' ) + outfile:write( '%%% DO NOT EDIT THIS FILE %%%\n' ) +end + +-- +-- Hacking help. +-- +function _direct( args ) + tprint( table.unpack( args ) ) +end + +-- +-- Checks version metch. +-- +tikz.checkVersion = +function( v ) + if v ~= tikz.version + then + error( 'version mismatch', 1 ) + end +end + +-- +-- Creates a color. +-- +tikz.colorRGB = +function( red, green, blue ) + return '{rgb,255:red,'..red..'; green,'..green..'; blue,'..blue..'}' +end + +-- +-- Makes a tikz scope. +-- Argument must be a function to call. +-- +tikz.scope = +function( args ) + args = flatten( args ) + if #args ~= 1 or type( args[ 1 ] ) ~= 'function' + then + error( 'scope needs a function parameter' ) + end + _direct{ [[\begin{scope}]] } + args[ 1 ]( ) + _direct{ [[\end{scope}]] } +end + +--==========================================================================-- +-- SHORTCUTS +--==========================================================================-- +tikz.p0 = tikz.p{ 0, 0 } + + +--==========================================================================-- +-- Running code within tikz environment. +--==========================================================================-- + +local env_nesting = 0 +local org_env +tikz.within = +function( version ) + if version ~= '*' and version ~= tikz.version + then + error( 'version mismatch', 1 ) + end + + env_nesting = env_nesting + 1 + if env_nesting > 1 + then + return + end + + org_env = _ENV + local nenv = { } + local mt = { } + mt.__index = + function( _, key ) + local zk = tikz[ key ] + if zk ~= nil + then + return zk + else + return org_env[ key ] + end + end + setmetatable( nenv, mt ) + local func = debug.getinfo( 2 ).func + debug.setupvalue( func, 1, nenv ) +end + +tikz.without = +function( ) + env_nesting = env_nesting - 1 + if env_nesting > 0 then return end + local func = debug.getinfo( 2 ).func + debug.setupvalue( func, 1, org_env ) +end diff --git a/Master/texmf-dist/tex/latex/luatikz/luatikz.sty b/Master/texmf-dist/tex/latex/luatikz/luatikz.sty new file mode 100644 index 00000000000..5847ab888a1 --- /dev/null +++ b/Master/texmf-dist/tex/latex/luatikz/luatikz.sty @@ -0,0 +1,5 @@ +\ProvidesPackage{luatikz}[2024/12/04 2.12.0 Luatikz] +%This package is just wrapper to load the luatikz code. +\RequirePackage{luacode} +\directlua{require('luatikz')} +\endinput diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index e764f309828..dc132182c92 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -545,7 +545,7 @@ my @TLP_working = qw( luamesh luamml luamodulartables luamplib luanumint luaoptions luaotfload luapackageloader luaplot luaprogtable luapstricks luaquotes luarandom - luaset luasseq luatex85 luatexbase luatexja luatexko luatextra + luaset luasseq luatex85 luatexbase luatexja luatexko luatextra luatikz luatodonotes luatruthtable luavlna luaxml lutabulartools luwiantype lwarp lxfonts ly1 lyluatex macrolist macros2e macroswap mafr magaz magicnum magicwatermark magra diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 8862dc13a39..fc845661efe 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -2374,6 +2374,7 @@ $standardtex 'luaprogtable','\.lua|' . $standardtex, 'luapstricks', '\.lua|' . $standardtex, 'luatexko', '\.lua|' . $standardtex, + 'luatikz', '\.lua|' . $standardtex, 'luatodonotes','\.lua|' . $standardtex, 'luavlna', 'luavlna.*\.lua|luavlna\.tex|' . $standardtex, 'luaxml', '\.lua|' . $standardtex, diff --git a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc index 88f3edaa7b8..9e1c720cb8a 100644 --- a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc @@ -76,6 +76,7 @@ depend luatex85 depend luatexbase depend luatexko depend luatextra +depend luatikz depend luatruthtable depend luavlna depend luaxml diff --git a/Master/tlpkg/tlpsrc/luatikz.tlpsrc b/Master/tlpkg/tlpsrc/luatikz.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/luatikz.tlpsrc |