#!/usr/bin/env texlua
-- $Id: test-luagraphlib.lua 3 2024-02-16 00:36:49Z reinhard $
-- Copyright (C) 2020 Reinhard Kotucha <reinhard.kotucha@web.de>
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-- MA 02110-1301, USA.
require('luagraphlib')
luagraphlib.import()
local fmt = string.format
local pi = math.pi
local sin = math.sin
local cos = math.cos
local arc_tan = math.atan
local sqrt = math.sqrt
local color = dofile(kpse.find_file('namedcolors.lua'))
-- gray color model
local gray = color.gray
-- rgb color model
local rgb = color.rgb
local x11 = color.rgb.x11
local svg = color.rgb.svg
-- cmyk color model
local cmyk = color.cmyk
local dvips = color.cmyk.dvips
local hks = color.cmyk.hks
function lines ()
setlinewidth(sp(65536)) -- 1 pt
moveto(0,0)
lineto(50,50)
lineto(100,0)
stroke()
end
function units ()
setlinewidth(2.3)
local unittab = {
{ len = pt(1), text = '1$\\,$pt' },
{ len = bp(1), text = '1$\\,$bp' },
{ len = dd(1), text = '1$\\,$dd' },
{ len = nd(1), text = '1$\\,$nd' },
{ len = mm(1), text = '1$\\,$mm' },
{ len = pc(1), text = '1$\\,$pc' },
{ len = cc(1), text = '1$\\,$cc' },
{ len = nc(1), text = '1$\\,$nc' },
{ len = cm(1), text = '1$\\,$cm' },
{ len = inch(1), text = '1$\\,$inch' },
}
for i,unit in ipairs (unittab) do
gsave()
translate (0, i*5 + 3)
text(unit.text, {align='left'})
moveto(12, 1)
rlineto(unit.len, 0)
stroke()
grestore()
end
end
function polar_star ()
local function star (r)
local theta = 144
moveto(cartesian(r, 90))
for i=0, 4 do
lineto(cartesian(r, i*theta + 90))
end
closepath()
end
setstrokecolor(dvips.BrickRed)
setfillcolor(svg.LightGoldenrod)
translate(25,25)
star(20)
paint()
translate(50,0)
star(20)
paint('eofill')
end
function arcs ()
local r = 10
gsave()
setfillcolor(svg.PaleTurquoise)
setstrokecolor(dvips.MidnightBlue)
moveto(0, r)
arc(r, r, r, 180, 270)
lineto(100-r, 0)
arc(100-r, r, r, 270, 360)
lineto(100, 50-r)
arc(100-r, 50-r, r, 0, 90)
lineto(r, 50)
arc(r, 50-r, r, 90, 180)
closepath()
paint()
grestore()
local r = 20
moveto(50,25)
setstrokecolor(dvips.BrickRed)
setfillcolor(svg.Goldenrod)
rlineto(cartesian(r, -100))
arc(50, 25, r, -100, 230)
scalepath(1, 0.5, 50, 25)
closepath()
paint()
end
function negative_arcs ()
local r1 = 10
local r2 = 20
translate(50,25)
setstrokecolor(dvips.BrickRed)
setfillcolor(svg.Goldenrod)
moveto(r2, 0)
arc(0, 0, r2, 0, 90)
lineto(0, r1)
arcn (0, 0, 10, 90, 0)
closepath()
paint()
end
function ellipses ()
setlinewidth(3)
moveto(25,25)
circle(10)
closepath()
stroke()
gsave()
translate(50,25)
moveto(0,0)
circle(10)
closepath()
scale(.7,1)
stroke()
grestore()
setstrokecolor(dvips.MidnightBlue)
translate(75,25)
moveto(0,0)
circle(10)
closepath()
scalepath(.7,1)
gsave()
setstrokecolor(dvips.BrickRed)
stroke()
grestore()
translate(5,0)
stroke()
moveto(0,0)
rectclip(-10,0,20,20)
translate(-5,0)
setstrokecolor(dvips.BrickRed)
moveto(0,0)
circle(10)
scalepath(.7,1)
closepath()
stroke()
end
function rectangle ()
setlinewidth(pt(0.4))
moveto(50,25)
rlineto(10,0)
rlineto(0,10)
stroke()
end
function fill_stroke ()
setlinewidth(3)
setstrokecolor(hks[47])
setfillcolor(dvips.Goldenrod)
gsave()
translate(25,25)
moveto(0,0)
circle(10)
closepath()
paint()
translate(0, -3)
text('1', {scale=2.5})
grestore()
gsave()
translate(50,25)
moveto(0,0)
circle(10)
gsave()
closepath()
setstrokecolor(rgb.hks[47])
fill()
translate(0, -3)
text('2', {scale=2.5})
grestore()
closepath()
stroke()
grestore()
gsave()
translate(75,25)
moveto(0,0)
circle(10)
gsave()
closepath()
stroke()
grestore()
closepath()
fill()
translate(0, -3)
text('3', {scale=2.5})
grestore()
end
function grid (x, y, w, h)
translate(x,y)
gsave()
rectclip(0, 0, w, h)
setstrokecolor(rgb.grid)
setlinewidth(0.1)
for i=0, w do
moveto(i,0)
rlineto(0,h)
end
for i=0, h do
moveto(0,i)
rlineto(w,0)
end
stroke()
setlinewidth(0.25)
for i=0, w, 5 do
moveto(i,0)
rlineto(0,h)
end
for i=0, h, 5 do
moveto(0,i)
rlineto(w,0)
end
stroke()
setlinewidth(0.4)
for i=0, w, 10 do
moveto(i,0)
rlineto(0,h)
end
for i=0, h, 10 do
moveto(0,i)
rlineto(w,0)
end
stroke()
setstrokecolor(gray.black)
setlinewidth(0)
for i=0, w, 10 do
moveto(i,0)
rlineto(0,h)
end
for i=0, h, 10 do
moveto(0,i)
rlineto(w,0)
end
stroke()
grestore()
setlinewidth(0.3)
rect(0,0,w,h)
stroke()
for i=0, w, 10 do
gsave()
translate(i, -4)
text(i)
grestore()
end
for i=0, h, 10 do
gsave()
translate(-1, i-1)
text(i, {align='right'})
grestore()
end
end
function text_scaling ()
translate(7,7)
grid(0,0,90,40)
setlinewidth(.5)
gsave()
setstrokecolor(svg.DarkGreen)
moveto(50,5)
rlineto(0,30)
stroke()
grestore()
gsave()
translate(50,25)
text('scale = 3', {scale=3})
translate(0,-10)
gsave()
text('extend = 3', {extend=3})
grestore()
translate(0,-10)
text('left aligned, slant = 0.1', {align='left', slant=.1})
text('right aligned, slant = -0.1', {align='right', slant=-.1})
grestore()
end
function bezier_curves ()
local radius = 30
setlinewidth(pt(.4))
setstrokecolor(gray.gray)
setlinecap('round')
gsave()
moveto(25,5)
setfillcolor(gray.black)
circle(1)
fill()
grestore()
gsave()
moveto(95,45)
setfillcolor(gray.black)
circle(1)
fill()
grestore()
gsave()
moveto(95,45)
rlineto(-15,0)
gsave()
setfillcolor(gray.black)
circle(1)
fill()
grestore()
stroke()
grestore()
for phi = 0, 135, 15 do
setlinewidth(pt(.4))
moveto(25,5)
rlineto(cartesian(radius,phi))
gsave()
setfillcolor{phi/180, 0, 1-phi/120}
setlinewidth(pt(.4))
circle(1)
fill()
grestore()
setstrokecolor(gray.gray)
stroke()
setlinewidth(pt(.4))
setstrokecolor{phi/180, 0, 1-phi/120}
moveto(25,5)
local x1, x2 = cartesian(radius,phi)
rcurveto(x1, x2, 55, 40, 70, 40)
stroke()
end
end
function colors ()
rect(0,0,100,50)
setfillcolor(gray.lightgray)
fill()
local function label (s)
gsave()
translate(1,4)
text(s, {align='left',
extend=1.333,
textcolor=dvips.BrickRed,
}
)
grestore()
end
translate(2,35)
local RGB = {
{1,1,1},
{1,1,0},
{0,1,1},
{0,1,0},
{1,0,1},
{1,0,0},
{0,0,1},
{0,0,0},
}
for i, color in ipairs(RGB) do
rect((i-1)*5,0, 5,10)
setfillcolor(color)
fill()
end
label ('RGB')
translate(0,-10)
local CMYK = {
{0,0,0,0},
{0,0,1,0},
{1,0,0,0},
{1,0,1,0},
{0,1,0,0},
{0,1,1,0},
{1,1,0,0},
{0,0,0,1},
}
for i,color in ipairs(CMYK) do
rect((i-1)*5,0, 5,10)
setfillcolor(color)
fill()
end
label ('CMYK')
translate(0,-10)
for i=1, 8 do
rect((i-1)*5,0, 5,10)
setfillcolor{1 - (i-1)/7}
fill()
end
label ('Gray')
translate(0,-10)
for i, color in ipairs(RGB) do
rect((i-1)*5,0, 5,10)
setfillcolor{.3*color[1] + .59*color[2] + .11*color[3]}
fill()
end
label ('NTSC gray')
end
function framed_text ()
grid(7,7,90,40)
setlinewidth(.2)
setstrokecolor(dvips.BrickRed)
setfillcolor(svg.LightGoldenrod)
gsave()
translate(45,5)
text('left aligned',
{ align = 'left',
slant = -.1,
sep = 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
}
)
text('right aligned',
{ align = 'right',
slant = .1,
sep = 2,
linewidth = 0.4,
fillcolor = svg.LightGoldenrod,
strokecolor = dvips.BrickRed,
textcolor = gray.black,
framed=true,
})
grestore()
gsave()
translate(45,10)
text('extended',
{ extend=3,
sep=2,
fillcolor = svg.LightGoldenrod,
strokecolor = dvips.BrickRed,
textcolor = gray.black,
framed=true,
})
grestore()
------------------
gsave()
translate(5,35)
text('without strut:',
{align = 'left',
sep = 2,
fillcolor=gray.white,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(5,30)
text('AAA',
{align = 'left',
sep = 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(17,30)
text('xxx',
{align = 'left',
sep = 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(26,30)
text('yyy',
{align = 'left',
sep = 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(5,25)
text('with strut:',
{align = 'left',
sep = 2,
fillcolor=gray.white,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(5,20)
text('AAA',
{align = 'left',
sep = 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
strut='Ay',
})
grestore()
gsave()
translate(17,20)
text('xxx',
{align = 'left',
sep = 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
strut='Ay',
})
grestore()
gsave()
translate(26,20)
text('yyy',
{align = 'left',
sep = 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
strut='Ay',
})
grestore()
------------------
gsave()
translate(55,35)
text('without strut:',
{align = 'left',
radius = 2,
fillcolor=gray.white,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(55,30)
text('AAA',
{align = 'left',
radius= 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(67,30)
text('xxx',
{align = 'left',
radius= 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(76,30)
text('yyy',
{align = 'left',
radius= 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(55,25)
text('with strut:',
{align = 'left',
radius= 2,
fillcolor=gray.white,
textcolor=gray.black,
framed=true,
})
grestore()
gsave()
translate(55,20)
text('AAA',
{align = 'left',
radius= 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
strut='Ay',
})
grestore()
gsave()
translate(67,20)
text('xxx',
{align = 'left',
radius= 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
strut='Ay',
})
grestore()
gsave()
translate(76,20)
text('yyy',
{align = 'left',
radius= 2,
fillcolor=svg.LightGoldenrod,
strokecolor=dvips.BrickRed,
textcolor=gray.black,
framed=true,
strut='Ay',
})
grestore()
end
function dashpatterns ()
gsave()
rectclip(0,0,100,100)
setlinewidth(1)
for i=5, 15 do
setdash({1,1,3,1}, i)
moveto(0, i*2)
lineto(100, i*2)
stroke()
end
for i=20, 30 do
setlinecap('round')
setdash({0,2,2,2}, i)
gsave()
setstrokecolor(dvips.BrickRed)
moveto(-6, i*2)
lineto(106, i*2)
stroke()
grestore()
moveto(0, i*2)
lineto(100, i*2)
stroke()
end
for i=35, 45 do
setlinecap('round')
setdash({0,2,0,2}, i)
gsave()
setstrokecolor(dvips.BrickRed)
moveto(-4, i*2)
lineto(104, i*2)
stroke()
grestore()
moveto(0, i*2)
lineto(100, i*2)
stroke()
end
grestore()
end
local function clockface (r)
moveto(0,0)
circle(r) -- outer circle
setstrokecolor{0}
setfillcolor{1}
paint('eofill')
r = r * .93
gsave()
setlinewidth(.03*r) -- second ticks
for i=0, 59 do
moveto(r,0)
lineto(.9*r,0)
stroke()
rotate(6)
end
grestore()
gsave()
setlinewidth(.05*r) -- 5 second ticks
for i=0, 11 do
moveto(r,0)
lineto(.83*r,0)
stroke()
rotate(30)
end
grestore()
end
local function hands (r, t)
local hour=t.hour%12 + t.min/60
gsave() -- hour
setlinewidth(.08*r)
moveto(-.08*r,0)
lineto(.6*r,0)
rotate(90-hour*360/12)
stroke()
grestore()
gsave() -- minute
setlinewidth(.05*r)
moveto(-.08*r,0)
lineto(.8*r,0)
rotate(90-t.min*6)
stroke()
grestore()
gsave() -- second
rotate(90-t.sec*6)
setlinewidth(.02*r)
moveto(-.1*r,0); lineto(.5*r,0)
moveto(.7*r,0); lineto(.96*r,0)
setstrokecolor{.5, 0, 0}
stroke()
gsave() -- small circle
setlinewidth(.04*r)
translate(.6*r,0)
moveto(0, 0)
circle(.1*r)
setstrokecolor{.5, 0, 0}
stroke()
grestore()
grestore()
end
function clock ()
setfillcolor{.9}
rect(5,5,180,90)
fill()
local function label (location, t)
gsave()
translate(0,25)
text('{\\bf '..location..'}',
{ scale=2.5,
textcolor = dvips.BrickRed,
framed=false,
})
grestore()
gsave()
translate(0,-30)
local dow = {'So','Mo','Di','Mi','Do','Fr','Sa'}
text(fmt('\\sf %s\\smash{\\hbox{,}} %d.$\\,$%d.$\\,$%d',
dow[t.wday], t.day, t.month, t.year),
{ scale=1.5,
sep=3,
strut='0',
textcolor = gray.black,
strokecolor = gray.black,
fillcolor = gray.white,
framed=true,
})
grestore()
end
local r = 20 -- clock radius
local t=(os.date('*t', os.time()))
translate(190/2,50)
label('Paris', t)
clockface(r)
hands(r,t)
local t=(os.date('*t', os.time() - 3600*6))
translate(-55,0)
label('New$\\,$York', t)
clockface(r)
hands(r,t)
translate(110,0)
local t=(os.date('*t', os.time() + 3600*8))
label('Tokyo', t)
clockface(r)
hands(r,t)
end
function metartest_1()
gsave()
setlinewidth(pt(0.4))
for i=0, 24 do
moveto (i*150/24,0)
lineto (i*150/24,80)
stroke()
gsave()
translate(i*150/24, -3.5)
text (i)
grestore()
end
for i=0, 16 do
moveto (0, 5*i)
lineto (150, 5*i)
stroke()
gsave()
translate(155, 5*i - pt(3))
text (i, {align='r'})
grestore()
end
setlinewidth(pt(3))
to_path(datafile('data/metar.data', 1, 3))
scalepath(150/24, 5)
gsave()
setlinecap('round')
setlinejoin('round')
setstrokecolor(svg.Goldenrod)
setstrokecolor(dvips.BrickRed)
setlinewidth(pt(.6))
stroke()
grestore()
gsave()
smooth()
setlinewidth(pt(.8))
setstrokecolor({.5,.5,1})
setstrokecolor(dvips.MidnightBlue)
stroke()
grestore()
grestore()
end
function antenna ()
translate(65,65)
scale(1.2, 1.2)
setlinewidth(pt(1))
setlinejoin('round')
setstrokecolor(gray.black)
local function dB_to_polar (data)
local fixed = {}
for _,coords in ipairs(data) do
fixed[#fixed+1] = {40 + coords[1], coords[2]}
end
return fixed
end
local patternfillcolor = {0.85}
local textscale = 0.8
moveto(0,0)
circle(40)
stroke()
to_path(polar_to_cartesian(
dB_to_polar(
readdatafile('data/ant/rfi15_915h.data',
function (a) return a[2], a[1] end))))
closepath()
setstrokecolor(dvips.BrickRed)
setfillcolor(patternfillcolor)
paint()
setstrokecolor(gray.black)
setlinewidth(pt(0.4))
for i = 10, 30, 10 do
moveto(0,0)
circle(i)
stroke()
end
for phi = 0, 350, 10 do
gsave()
rotate(phi)
translate(45, 0)
rotate(-90)
text('\\phantom{$^\\circ$}'..phi..'$^\\circ$',
{
scale = textscale,
}
)
grestore()
end
for phi = 15, 360, 15 do
moveto(cartesian(5, phi))
lineto(cartesian(40, phi))
stroke()
end
for phi = 45, 360, 45 do
moveto(cartesian(0, phi))
lineto(cartesian(40, phi))
stroke()
end
for phi = 1, 360 do
moveto(cartesian(40, phi))
lineto(cartesian(42, phi))
stroke()
end
for phi = 5, 360, 5 do
moveto(cartesian(40, phi))
lineto(cartesian(43, phi))
stroke()
end
for phi = 10, 360, 10 do
moveto(cartesian(40, phi))
lineto(cartesian(44, phi))
stroke()
end
setstrokecolor(gray.black)
setlinewidth(pt(0.4))
for i = 10, 30, 10 do
moveto(0,0)
circle(i)
stroke()
end
for phi = 0, 350, 10 do
gsave()
rotate(phi)
translate(45, 0)
rotate(-90)
text('\\phantom{$^\\circ$}'..phi..'$^\\circ$',
{
scale = textscale,
}
)
grestore()
end
for phi = 15, 360, 15 do
moveto(cartesian(5, phi))
lineto(cartesian(40, phi))
stroke()
end
for phi = 45, 360, 45 do
moveto(cartesian(0, phi))
lineto(cartesian(40, phi))
stroke()
end
for phi = 1, 360 do
moveto(cartesian(40, phi))
lineto(cartesian(42, phi))
stroke()
end
for phi = 5, 360, 5 do
moveto(cartesian(40, phi))
lineto(cartesian(43, phi))
stroke()
end
for phi = 10, 360, 10 do
moveto(cartesian(40, phi))
lineto(cartesian(44, phi))
stroke()
end
for _,dB in ipairs{10, 20, 30} do
gsave()
translate(dB, 0)
translate(1, 0)
rotate(270)
text('$-'..40-dB..'\\,$dB',
{
scale = textscale,
sep = 1,
framed = true,
fillcolor = patternfillcolor,
strokecolor = patternfillcolor,
}
)
grestore()
end
end
function squares ()
local function is_odd (n)
if n%2 == 1 then return true end
end
local off = 0
for i = 0, 9 do
for k = 0, 5 do
if is_odd(i) then off = 6 end
rect (k*20+off, i*10, 10, 10)
fill()
off = 0
end
end
setlinewidth(.5)
for i = 0, 10 do
moveto(0, i*10)
lineto(116, i*10)
stroke()
end
end
function jiggling ()
local function is_odd (n)
if n%2 == 1 then return true end
end
local function wrect (x, y)
rect(x*4, y*4, 4, 4)
rectn(x*4+1, y*4+1, 2, 2)
fill()
end
local function brect (x, y)
rect(x*4+1, y*4+1, 2, 2)
end
for x=0, 24 do
if is_odd(x) then
for y=0, 24 do
if is_odd(y) then
wrect(x, y)
else
brect(x, y)
end
end
else
for y=0, 24 do
if is_odd(y) then
brect(x, y)
else
wrect(x, y)
end
end
end
end
end
function arrowheads ()
local ahead1 = arrowshape { len = 10, wd = 3, inset = 1, offset = 7 }
local ahead2 = arrowshape { len = 10, wd = 3, inset = 1 }
local ahead3 = arrowshape { len = 10, wd = 3, inset = 3 }
local ahead4 = arrowshape { len = 8, wd = 4 }
local ahead5 = arrowshape { len = 3, wd = 2 }
local ahead5 = arrowshape { len = 3, inset = 0.75 }
grid (0, 0, 100, 50)
gsave()
ahead1 (10, 10, 0)
ahead1 (30, 10, 30)
ahead3 (50, 10, 45)
ahead4 (70, 10, 45)
ahead5 (90, 10, 45)
for ang = 1, 12 do
ahead2 (40, 30, ang*30)
end
for ang = 1, 12 do
ahead3 (70, 30, ang*30)
end
grestore()
end
-- Local Variables:
-- mode: Lua
-- TeX-engine: luatex
-- lua-indent-level: 2
-- indent-tabs-mode: nil
-- coding: utf-8-unix
-- End:
-- vim:set tabstop=2 expandtab: