% !TEX TS-program = LuaLaTeX
% !TEX encoding = UTF-8 Unicode 
% !TEX root = ../../mal-core.tex

\def\balicek#1{\textsf{#1}}

\gdef\mujnazevCS{Několik postřehů k Asymptote}
\gdef\mujnazevEN{Several notes on Asymptote}
\gdef\mujnazevPR{\mujnazevCS}
\gdef\mujnazevDR{\mujnazevEN}
\gdef\mujauthor{Pavel Stříž}

\bonushyper

\nazev{\mujnazevCS}

\nazev{\mujnazevEN}

\author{\mujauthor}

%\Adresa{}

\Email{pavel@striz.cz}

%\Abstrakt{}
%\smallskip
%\KlicovaSlova{}

%\Abstract{}
%\smallskip
%\KeyWords{}

\section{Vzpomínky na Asymptote}
Na své první pokusy s 
\href{https://asymptote.sourceforge.io/}{Asymptote} si pamatuji dobře, neb jsem řešil tři školské grafy ve 3D paralelně v Asymptote a přes 
\href{http://jmol.sourceforge.net/}{Jmol} v prostředí 
\href{https://www.sagemath.org/}{Sage.} 
Od té doby již neužíváme balíček 
\href{https://ctan.org/pkg/movie15}{\balicek{movie15},} ale jeho nástupce balíček 
\href{https://ctan.org/pkg/media9}{\balicek{media9}.}
\begin{lstlisting}
$ texdoc movie15 media9
\end{lstlisting}

Inspirací ke studiu mi byla hlavně tato galerie, \href{http://www.piprime.fr/asymptote/}{\url{http://www.piprime.fr/asymptote/}}. Autorem ukázek je Philippe Ivaldi.


\section{Instalace Asymptote}
Poněvadž pracuji na starších strojích, vždy něco nejede, byť používám poslední verzi \TeX Live. V tomto případě se mi nepodařilo generovat pdf skrz starší grafickou kartu, až po zadání

\noindent\hfil
\verb|export MESA_GL_VERSION_OVERRIDE=1.2|

\noindent
do souboru \texttt{\char`~/.bashrc} a načtení přes \texttt{source \char`~/.bashrc} se mi to podařilo, ale to jen pro obrázky vykreslené ve 2D.
U hledání problému mi pomohly parametry Asymptote
\texttt{-v},
\texttt{-vv} (nebo \texttt{-v -v}) a hlavně
\texttt{-vvv} (nebo \texttt{-v -v -v}). Ve výpisech lze jít až do páté úrovně (str.\,168 dokumentace). Linuxový \texttt{man} hovoří o \texttt{-v} a jisté možnosti jít hlouběji, ale nehovoří konkrétně.
\begin{lstlisting}
$ texdoc asy # nebo
$ man asy
\end{lstlisting}


Přesedl jsem na novější stroj. Na Xubuntu 20.04 bylo potřeba doinstalovat knihovnu \texttt{freeglut3}, speciálně se jednalo o knihovnu \texttt{libglut.so.3}.
\begin{lstlisting}
$ sudo apt install freeglut3
\end{lstlisting}

Poté se mi podařilo vyrenderovat všechny grafy předchozího článku Rudolfa Blaška.


\section{WebGL}
Zajímavá je i situace, když chceme získat webovou verzi grafů. Možná si říkáte, proč je to tak důležité. Pokud pracujete v linuxovém prostředí, tak firma Adobe zrušila podporu pro prohlížeč pdf 
\href{https://get.adobe.com/cz/reader/otherversions/}{Adobe Reader}. 
Poslední známá verze je 9.5.5 pro 32bitové stroje. Uživatelé pak musí sáhnout po virtuálním stroji typu
\href{https://www.virtualbox.org/}{Oracle VM VirtualBox,} po
\href{https://www.winehq.org/}{Wine} 32bitové verzi, míchat 32bitové a 64bitové aplikace či zkusit podobné řešení (%
\href{https://www.foxitsoftware.com/pdf-reader/}{FoxIt Reader,} ale také jede jen něco).
Stručně řečeno, prakticky na libovolném %chytrém telefonu 
stroji s Microsoft Windows či MacOS
3D grafy interaktivně v pdf uvidíte, ale zápasíte s tím pod Linuxem.
%a vhodný prohlížeč nenajdete.


O WebGL (vhodné i pro chytré telefony) a~nastavení je zmínka na str.\,137 v dokumentaci 
\href{https://asymptote.sourceforge.io/asymptote.pdf}{Asymptote}. Poslední verze programu je 2.65.
\begin{lstlisting}
$ texdoc asymptote
\end{lstlisting}

Vzal jsem si jeden ze vzniklých asy souborů předchozího článku, horní graf, obr.~\ref{obr03} na str.~\pageref{obr03}, zkopíroval na \texttt{webgl-pokus.asy} a~vyčistil do této minimální podoby (vymazání úvodních definic, globálního definování neužitých barev a promazání prázdných řádků):
\begin{lstlisting}
import graph3;
import palette;
size(175,175,IgnoreAspect);
currentprojection=perspective(2,.55,0.25);
real f(pair z) {return sin(z.x)*sin(z.y);}
draw(surface(f,(-pi,-pi),(pi,pi),nx=24,Spline),lightblue,render(merge=true));
surface f=surface(f,(-pi,-pi),(pi,pi),24,Spline);
draw(f,mean(palette(f.map(zpart),Rainbow(24))),brown);
draw(Label("$x$",1),(-1.2pi,0,0)--(1.2pi,0,0),brown,Arrow3);
draw(Label("$y$",1),(0,-1.2pi,0)--(0,1.2pi,0),brown,Arrow3);
draw(Label("$z$",1),(0,0,-1.2)--(0,0,1.2),brown,Arrow3);
label("$z=\sin{x}\cdot\sin{y}$",(.5,.5,-1.35),SE,deepblue);
\end{lstlisting}

O výstupech hovoří manuál v kapitole~8.29 \texttt{three}, speciálně na str.\,137. Prvně jsem si vyzkoušel náhled v okně:
\begin{lstlisting}
$ asy -V webgl-pokus.asy
\end{lstlisting}

Nasledované pokusem o vygenerování webové stránky.
\begin{lstlisting}
$ asy -f html webgl-pokus.asy
\end{lstlisting}

Vzniká soubor \texttt{webgl-pokus.html}, který se mi podařilo otevřít i na starém notebooku. Alternativou je zadat výstupní formát přímo v asy souboru (středník na konci řádků je nutný, je součástí syntaxe jazyka):
\begin{lstlisting}
import settings;
settings.outformat="html";
// outformat="html";
\end{lstlisting}

Bez prázdných řádků soubor vypadá přibližně takto:

\begin{lstlisting}
<!DOCTYPE html>
<!-- Use the following line to embed this file within another web page:
<iframe src="webgl-pokus.html" width="176" height="176" frameborder="0"></iframe>
-->
<html lang="">
<head>
  <title>webgl-pokus</title>
  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  <meta name="viewport" content="user-scalable=no"/>
  <script
  src="https://vectorgraphics.github.io/asymptote/base/webgl/asygl-1.00.js">
  </script>
  <script>
    canvasWidth=176;
    canvasHeight=176;
    absolute=false;
    // ...
    Centers=[
    [-10.3373,-38.23629,-223.1933],
    [81.93387,-1.42227,-289.569],
    [0.5386997,67.84467,-262.8985],
    [9.891595,-74.96387,-327.4771],
    ];
  </script>
</head>
<body style="overflow: hidden;" onload="webGLStart();">
  <canvas id="Asymptote" width="176" height="176" style="border: none;">
  </canvas>
</body>
</html>
\end{lstlisting}


Nepodařilo se mi dle návodu na str.\,137 vložit vzniklou webovou stránku do další přes \texttt{<object>} ani přes \texttt{<iframe>} jak radí poznámka ve vzniklém souboru. V konzoli se píše
\texttt{SecurityError: Permission denied to access property "document"{} on cross-origin object}.

Jisté řešení nabízí odpovědi na 
\href{https://stackoverflow.com/questions/36333978/error-permission-denied-to-access-property-document}{\url{https://stackoverflow.com/questions/36333978/error-permission-denied-to-access-property-document}}, ale to je bezpečnostní riziko.
Vyčištěním vzniklého souboru na úroveň prostého JavaScriptu a přes \texttt{<canvas>} se mi sice pořadilo dostat jeden graf na webovou stránku, ale jen jeden. Ideální je zůstat u hypertextových odkazů na vznikající soubory dle vzoru galerií na 
\href{https://asymptote.sourceforge.io/gallery/}{\url{https://asymptote.sourceforge.io/gallery/}}.

Pro badatele jistě stojí za pozornost možnost konverze PostScriptu do formátu asy s možností náhledu a následné editace:
\begin{lstlisting}
$ pstoedit -f asy <soubor.eps> <soubor.asy>
$ asy -V <soubor.asy>
\end{lstlisting}

V případě problémů s písmy se u 
\href{https://sourceforge.net/projects/pstoedit/}{\texttt{pstoedit}} používá parametr \texttt{-dt}.


\section{Ovládání \TeX ové proměnné mimo \TeX{}}

Rudolf Blaško byl spokojený s prvními výstupy, ale u jeho knihy bylo potřeba předchozí kroky zautomatizovat, jednalo se konkrétně o definice v prostředí \texttt{asydef}, které bylo potřeba změnit. Zdá se, že ani parametry z příkazového řádku programu \texttt{asy} tyto definice nemění. Chceme totiž knihu nechat beze změny, ale zároveň si vygenerovat webové stránky s 3D objekty. 

Vyřešil jsem to přepínačem na \TeX ové úrovni, který řídí dávkový soubor. Ukažme si minimální ukázku. Tento blok jsem si přidal za autorovy definice.

\begin{lstlisting}
\newcount\prepinac
\input ovladani.tex
\ifnum\prepinac=1
\begin{asydef}
settings.outformat="html";
settings.inlineimage=false;
settings.embed=false;
\end{asydef}
\fi
\end{lstlisting}

V dávkovém souboru pak stačí mít něco takového.

\begin{lstlisting}
soubor="ovladani.tex"
# Získání pdf knihy...
echo "\\prepinac=0" >$soubor
lualatex kniha.tex # plus další příkazy
# Generování html s 3D objekty...
echo "\\prepinac=1" >$soubor
lualatex kniha.tex # plus další příkazy
\end{lstlisting}

Tento přístup se používá, když chceme vygenerovat několik verzí knihy, např. knihu ve více šablonách, verzi s barevnými a černobílými obrázky, verzi na tisk a na obrazovku, verzi s a bez 3D objektů, pracovní a konečnou verzi čísla časopisu ap.



\section{Generování asy souborů přes R: jednoduchá ukázka}

O interaktivní 3D grafice jsem poprvé četl ve Zpravodaji Čs. sdružení uživatelů \TeX u od Romana Plcha, viz \url{https://www.cstug.cz/bulletin/pdf/2013-1.pdf}. Tam je zmínka o generování asy souborů, včetně jazyka R, konkrétně se jednalo o knihovnu 
\href{https://cran.r-project.org/web/packages/misc3d/misc3d.pdf}{\texttt{misc3d}} 
zmíněnou na str.\,40. Knihovna umí exportovat objekt \texttt{Triangles3D}, který se musí získat. Na knihovně staví novější knihovna 
\href{https://cran.r-project.org/web/packages/plot3D/}{\texttt{plot3D}.} 

Zvláštní kategorii tvoří knihovna
\href{https://cran.r-project.org/web/packages/rgl/}{\texttt{rgl}.}
%
Přišlo mně zajímavé vyzkoušet export do asy, tím lze získat 3D model v pdf, ale zároveň interaktivní webovou stránku (WebGL), proto nepoužiji příkaz \texttt{writeWebGL}, ale \texttt{writeASY}. Zkusme si minimální ukázku a v tomto článku se zaměřím už jen na webovou stránku.

Připravíme si soubor \texttt{test-rgl.R}:

\begin{lstlisting}
# install.packages("rgl")
library(rgl)
with(iris, plot3d(Sepal.Length, Sepal.Width, Petal.Length, type="s", col=as.numeric(Species)))
writeASY()
\end{lstlisting}

Spustíme:

\begin{lstlisting}
$ Rscript test-rgl.R
\end{lstlisting}

S největší pravděpodobností dostaneme chybovou hlášku od programu Asymptote. Psal jsem autorovi, chyba je opravena, ale ještě nová verze není ve všech linuxových a \TeX ových distribucích. Nepomůže nám ani pokus přes \texttt{writeASY(ver244=TRUE)}.

Vzniká nám soubor \texttt{scene.asy}, který upravíme. Do 2. řádku zasáhneme: \texttt{settings.outformat = "html";} a vymažeme 5 řádků, od \texttt{currentlight = light(} po nejbližší \texttt{);}.

Spouštíme následující řádky a dostáváme takový výsledek.

\begin{lstlisting}
$ asy -v scene.asy
$ firefox scene.html
\end{lstlisting}

\noindent
\hfil
\includegraphics[width=8cm]{test-rgl-1.png}

Badatele odkazuji na prozkoumání \url{https://cran.r-project.org/web/packages/rgl/vignettes/rgl.html}.


\section{Generování asy souborů přes R: pokročilejší ukázka}

V IB č.\,1/2018 jsem na str.\,13--15 zmínil jednoduché 
\href{https://www.statspol.cz/wp-content/uploads/2018/06/IB_1_2018.pdf}{ukázky} 
z manažerského rozhodování, z oblasti rozhodování při riziku. Chtěl bych si zkusit 
\href{https://cran.r-project.org/web/packages/gMOIP/vignettes/polytope_3d.html}{obdobné grafy,} ale interaktivní. Představím vám knihovnu 
\href{https://cran.r-project.org/web/packages/gMOIP/}{gMOIP,}
resp. mohu doporučit webové stránky autora (\url{https://github.com/relund/gMOIP}) a jeho blog (\url{https://www.research.relund.dk/}). 

Naše problémy jsou, že budeme chtít víc 3D modelů a určitě nebudeme chtít dělat ruční zásahy. Ukážeme si zásahy do textových souborů přes Lua, je to jazyk založený na C++, který dominuje v \TeX ovém světě a hraje nemalou roli ve světě počítačových her. Speciální pozornost by si zasloužila knihovna 
\href{http://www.inf.puc-rio.br/~roberto/lpeg/}{LPeg,} která si získala místo ve světě regulárních výrazů.

Připravíme si soubor \texttt{test-gmoic.R}:

\begin{lstlisting}
# install.packages("gMOIP")
library(gMOIP)
# definice
A <- matrix( c(3, 2, 5,  2, 1, 1,  1, 1, 3,  5, 2, 4), nc = 3, byrow = TRUE)
b <- c(55, 26, 30, 57)
obj <- c(20, 10, 15)
view <- matrix( c(-0.45, -0.446, 0.77, 0, 0.886, -0.32, 0.33, 0, 0.098, 0.835, 0.54, 0, 0, 0, 0, 1), nc = 4)
# první obrázek
loadView(v = view, zoom = 0.75)
plotPolytope(A, b, faces = c("c","c","c"), type = c("c","i","i"), plotOptimum = TRUE, obj = obj)
rgl::writeASY(outtype = "pdflatex", prc = TRUE, title = "polytope-1") 
# druhý obrázek
loadView(v = view, zoom = 0.75)
plotPolytope(A, b, type = c("c","c","i"), plotOptimum = TRUE, obj = obj, plotFaces = FALSE)
rgl::writeASY(outtype = "pdflatex", prc = TRUE, title = "polytope-2")
\end{lstlisting}

V dalším kroku si připravíme \TeX ový dokument \texttt{asy-pres-r.tex}:

\begin{lstlisting}
\documentclass[a4paper]{article}
\usepackage[luatex]{graphicx}
\usepackage{asymptote}
\begin{document}
\input{polytope-1.tex}\par
\input{polytope-2.tex}
\end{document}
\end{lstlisting}

Následuje soubor v Lua, který nám upravuje získané soubory, nazval jsem jej \texttt{smaz-light.lua}:

\begin{lstlisting}
-- Načtení souboru
nazev=arg[1]
print("Zpracovávám soubor "..nazev)
soubor=io.open(nazev)
obsah=soubor:read("*all")
soubor:close()
-- Zásah do souboru
obsah=unicode.utf8.gsub(obsah,"currentlight =.-%);", "", 1)
obsah=unicode.utf8.gsub(obsah, "settings%.inlineimage=true;", "settings.inlineimage=false;", 1)
-- Přepsání původního souboru
kam=io.open(nazev,"w")
kam:write(obsah)
kam:close()
\end{lstlisting}
% obsah=unicode.utf8.gsub(obsah, "settings%.outformat=\"\";", "settings%.outformat=\"html\";", 1)

Nyní nezbývá, než si připravit dávkový soubor \texttt{davka.sh}, který spustíme přes \texttt{bash davka.sh}:

\begin{lstlisting}
# Základ generování asy souborů
zaklad="asy-pres-r"
Rscript test-gmoic.R
lualatex --shell-escape $zaklad.tex 1>/dev/null 2>&1
# Úpravy v asy souborech
for soubor in `find -iname $zaklad-\*.asy`; do
texlua smaz-light.lua $soubor
asy -v $soubor
asy -v -f html $soubor
done
# Náhled na výsledky
firefox $zaklad-*.html
\end{lstlisting}

Co se přesně děje? Z R se vygenerují dva \TeX ové soubory, které použije \TeX{} a při prvním běhu vygeneruje asy soubory. Do nich zasáhneme na textové úrovni a přes Asymptote vygenerujeme 3D objekty a webové stránky, které si otevřeme ve webovém prohlížeči. 
Výhoda tohoto přístupu je, že u dalších běhů Lua\LaTeX u vysázíme v \texttt{asy-pres-r.pdf} 3D modely. Vedle toho máme dostupnou interaktivní webovou verzi.


Zde je náhled na očekávaný výsledek ve dvou záložkách prohlížeče.%
\smallskip

\noindent
\fboxsep=0pt
\fboxrule=1pt
\fbox{\includegraphics[height=40.7mm]{asy-pres-r-1.png}}\hfill
\fbox{\includegraphics[height=40.7mm]{asy-pres-r-2.png}}%
%\smallskip



