%\VignetteIndexEntry{A guide to the TurtleGraphics package} %\VignetteEngine{knitr::knitr} \documentclass[11pt]{article} \usepackage[dvips,a4paper,left=2.5cm,right=2.5cm,foot=1.0cm, headheight=1.0cm,top=2.0cm,margin=2.5cm]{geometry} \linespread{1.1} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage[english]{babel} \selectlanguage{english} \usepackage{xspace} \usepackage{lmodern} \usepackage{amsmath,amssymb,amsfonts} \RequirePackage{graphicx,verbatim,longtable} \usepackage{mdwlist} \usepackage{rotating} \usepackage{hyperref} \hypersetup{colorlinks=true, linkcolor=black, citecolor=black, urlcolor=blue} \setlength{\pdfpagewidth}{\paperwidth} \setlength{\pdfpageheight}{\paperheight} \usepackage{caption} \captionsetup{font=small,labelfont=bf,labelsep=period,justification=centering} \addto\captionsenglish{\renewcommand{\figurename}{Fig.}} \addto\captionsenglish{\renewcommand{\tablename}{Tab.}} \setlength{\topsep}{1pt} % wplywa m.in. na odstep dla verbatim \tolerance=500 \predisplaypenalty=0 \clubpenalty=1000 \widowpenalty=1000 \begin{document} <>= options(digits=7) options(width=73) require('knitr') # require('tikzDevice') # # options(tikzDefaultEngine = 'pdftex') # # options(tikzLatexPackages = c( # dolaczanie uzywanych pakietow TeX-a # '\\usepackage{amsmath,amssymb,amsfonts}', # pakiety AMS # '\\usepackage{tikz}', # # '\\usepackage[MeX,T1,plmath]{polski}', # obsluga m.in. polskich ogonkow # '\\usepackage[utf8]{inputenc}', # '\\usepackage[T1]{fontenc}', # '\\usetikzlibrary{calc}', # '\\usepackage[english]{babel}', # '\\selectlanguage{english}', # '\\usepackage{standalone}' # )) # # options(tikzMetricsDictionary='~/R/tikzMetrics') # # options(tikzDocumentDeclaration = '\\documentclass[11pt]{standalone}\n') # # options(tikzMetricPackages = c( # '\\usepackage[utf8]{inputenc}', # '\\usepackage[T1]{fontenc}', # '\\usepackage{amsmath,amssymb,amsfonts}', # '\\usetikzlibrary{calc}', # '\\usepackage[english]{babel}', # '\\selectlanguage{english}' # )) # opts_knit$set(progress = TRUE, verbose = TRUE) opts_chunk$set( keep.source=TRUE, out.width='4.5in', fig.width=6, fig.height=6/sqrt(3), # fig.path='figures-knitr/', # cache.path='cache-knitr/', cache=FALSE, tidy=FALSE, # dev='cairo_pdf', # dev.args=list(pointsize=11), # dev='tikz', # external=TRUE, fig.align='center', size='small' ) # knit_theme$set(knit_theme$get('solarized-light')) @ % \definecolor{fgcolor}{gray}{0} % \renewcommand{\hlnumber}[1]{\textcolor[gray]{0.2}{#1}}% % \renewcommand{\hlfunctioncall}[1]{\textbf{#1}}% % \renewcommand{\hlstring}[1]{\textcolor[gray]{0.2}{\textit{#1}}}% % \renewcommand{\hlkeyword}[1]{\textbf{#1}}% % \renewcommand{\hlargument}[1]{\textcolor[rgb]{0.2,0.2,0.2}{\textsl{#1}}}% % \renewcommand{\hlcomment}[1]{\textcolor[gray]{0.5}{\it\textsf{#1}}}% % \renewcommand{\hlroxygencomment}[1]{\textcolor[gray]{0.5}{\it\textsf{#1}}}% % \renewcommand{\hlformalargs}[1]{\textcolor[rgb]{0.69,0.25,0.03}{#1}}% % \renewcommand{\hleqformalargs}[1]{\textcolor[rgb]{0.69,0.25,0.03}{#1}}% % \renewcommand{\hlassignement}[1]{\textcolor[gray]{0}{\textbf{#1}}}% % \renewcommand{\hlpackage}[1]{\textcolor[rgb]{0.59,0.71,0.15}{#1}}% % \renewcommand{\hlslot}[1]{\textit{#1}}% % \renewcommand{\hlsymbol}[1]{\textcolor[cmyk]{0,0,0,1}{#1}}% % \renewcommand{\hlprompt}[1]{\textcolor[cmyk]{0,0,0,0.5}{#1}}% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{center} {\Huge A Guide to the \textsf{TurtleGraphics} Package for \textsf{R}} \bigskip {\LARGE A. Cena, M. Gagolewski, B.~\.{Z}oga\l{}a-Siudem, M. Kosi\'{n}ski,\\ N. Potocka} \medskip \href{http://www.gagolewski.com/software/TurtleGraphics/}{http://www.gagolewski.com/software/TurtleGraphics/} %\begin{figure}[hbt!] %\centering %\includegraphics[width=1in]{turtle2.png} %\end{figure} \end{center} \tableofcontents \newpage \section{The \textsf{TurtleGraphics} Package Introduction} The \textsf{TurtleGraphics} package offers R users the so-called ``turtle graphics'' facilities known from the Logo programming language. The key idea behind the package is to encourage children to learn programming and demonstrate that working with computers can be fun and creative. The \textsf{TurtleGraphics} package allows to create either simple or more sophisticated graphics on the basis of lines. The Turtle, described by its location and orientation, moves with commands that are relative to its position. The line that it leaves behind can be controlled by disabling it or by setting its color and type. The \textsf{TurtleGraphics} package offers functions to move the turtle forward or backward by a given distance and to turn the Turtle by a chosen angle. The graphical options of the plot, for example the color, type or visibility of the line, can also be easily changed. Try it yourself. Enjoy and have fun! \section{Installation And Usage of The Package} \subsection{Installation of the Package} To install the \textsf{TurtleGraphics} package use the following calls. <>= install.packages("TurtleGraphics") @ Then you load the package by calling the \textsf{library()} function: <>= library("TurtleGraphics") @ \subsection{The Basics} \subsubsection{Moving the Turtle} \paragraph{\textsf{turtle\_init}.} To start, call the \textsf{turtle\_init()} function. It creates a plot region and places the Turtle in the Terrarium's center, facing north. <>= turtle_init() @ By default its size is 100 by 100 units. You can easily change it by passing appropriate values to the \textsf{width} and \textsf{height} arguments (e.g.~\textsf{turtle\_init(width=200, height=200)}). To define what happens if the Turtle moves outside the plot region, you can set the \textsf{mode} option. The default value, \textsf{"clip"}, means that the Turtle can freely go outside the board (but it will not be seen). The \textsf{"error"} option does not let the Turtle out of the Terrarium -- if the Turtle tries to escape, an error is thrown. The third value, \textsf{"cycle"}, makes the Turtle come out on the other side of the board if it tries to cross the border. \paragraph{\textsf{turtle\_forward} and \textsf{turtle\_backward}.} There are two main groups of functions that may be used to move the Turtle. The first group consists in the \textsf{turtle\_forward()} and the \textsf{turtle\_backward()} functions. Their arguments define the distance you desire the Turtle to move. For example, to move the Turtle forward by a distance of 10 units, use the \textsf{turtle\_forward()} function. To move the Turtle backwards you can use either the \textsf{turtle\_forward()} function with a negative number as an argument, or simply use the \textsf{turtle\_backward()} function. % <>= % file <- paste("figure_1", ".pdf", sep="") % pdf(file=file, onefile=FALSE) % turtle_init() % turtle_forward(dist=30) % dev.off() % @ % % \begin{center} % <>= % cat("\\includegraphics[width=10cm]{", file, "}\n\n", sep="") % @ % \end{center} <>= turtle_init() turtle_forward(dist=30) @ <>= <> turtle_backward(dist=10) @ \clearpage \paragraph{\textsf{turtle\_right} and \textsf{turtle\_left}.} The other group of functions deals with the Turtle's rotation. \textsf{turtle\_left} and the \textsf{turtle\_right} change the Turtle's direction by a given angle. <>= <> turtle_right(angle=90) turtle_forward(dist=10) turtle_left(angle=135) turtle_forward(dist=14) turtle_left(angle=90) turtle_forward(dist=14) turtle_left(angle=135) turtle_forward(dist=10) @ \clearpage \subsubsection{Additional Options} Let's discuss some additional features you can play with. \paragraph{\textsf{turtle\_up} and \textsf{turtle\_down}.} To disable the path from being drawn you can use the \textsf{turtle\_up()} function. Let's consider a simple example. Turn the Turtle to the right by 90 degrees and then use the \textsf{turtle\_up()} function. Now, when you move forward, the path is not visible. If you want the path to be drawn again you should call the \textsf{turtle\_down()} function. <>= <> turtle_up() turtle_right(90) turtle_forward(dist=10) turtle_right(angle=90) turtle_forward(dist=17) turtle_down() turtle_left(angle=180) turtle_forward(dist=34) @ % \clearpage \paragraph{\textsf{turtle\_hide} and \textsf{turtle\_show}.} Similarly, you may show or hide the Turtle's image, using the \textsf{turtle\_show()} and \textsf{turtle\_hide()} functions, respectively. If you are calling a bunch of functions at a time, it is strongly recommended to hide the Turtle first; it will speed up the drawing process, see also \textsf{turtle\_do()}. % <>= % <> % turtle_hide() % turtle_left(angle=150) % turtle_forward(dist=20) % turtle_show() % @ % % \begin{center} % <>= % cat("\\includegraphics[width=10cm]{", file, "}\n\n", sep="") % @ % \end{center} % % <>= % turtle_hide() % turtle_left(angle=150) % turtle_forward(dist=20) % turtle_show() % @ \clearpage \paragraph{\textsf{turtle\_col}, \textsf{turtle\_lty} and \textsf{turtle\_lwd}.} To change the style of the Turtle's trace, you can use the \textsf{turtle\_col()}, \textsf{turtle\_lty()}, and \textsf{turtle\_lwd()} functions. The first one, as you can easily guess, changes the path color. For example, if you wish to change the trace to green, try: <>= <> turtle_hide() turtle_col(col="green") turtle_left(angle=150) turtle_forward(dist=20) turtle_left(angle=60) turtle_forward(dist=20) turtle_show() @ A comprehensive list of available colors is provided by the \textsf{colors()} function. \clearpage The \textsf{turtle\_lty()} and \textsf{turtle\_lwd()} functions change the style of the path. To change the ``type'' of the path, pass as an argument a number from $0$ to $6$ -- each of these denotes a different type of the line ($0=$blank, $1=$solid (default), $2=$ dashed, $3=$ dotted, $4=$ dotdash, $5=$ longdash, $6=$ twodash). To change the width of the line, use the \textsf{turtle\_lwd()} function. % As an argument you pass a width you desire (but don't exaggerate!). <>= <> turtle_left(angle=150) turtle_lty(lty=4) turtle_forward(dist=17) turtle_lwd(lwd=3) turtle_forward(dist=15) @ \clearpage \paragraph{\textsf{turtle\_status}, \textsf{turtle\_getpos} and \textsf{turtle\_getangle}.} If you got lost in the Terrarium (it's a jungle out there!), don't worry! Just use the \textsf{turtle\_status()} function: it returns the current drawing settings. It provides you with the information on the width and height of the terrarium, whether the Turtle and its path are visible, where the Turtle is placed right now and at which angle, and so on. <>= turtle_init() turtle_status() @ If you just want to know where the Turtle is, or what is its direction, try the \textsf{turtle\_getpos()} and \textsf{turtle\_getangle()} functions, respectively. <>= turtle_init() turtle_getpos() turtle_getangle() @ \clearpage \paragraph{\textsf{turtle\_reset}, \textsf{turtle\_goto}, and \textsf{turtle\_setpos}.} If you wish to relocate the Turtle back to the starting position and reset all of the graphical parameters, call the \textsf{turtle\_reset()} function. The \textsf{turtle\_goto()} and \textsf{turtle\_setpos()} functions, on the other hand, asks the Turtle to go to the desired position. The latter never draws any path. % <>= % file <- paste("figure_8", ".pdf", sep="") % pdf(file=file, onefile=FALSE) % turtle_init() % turtle_forward(dist=30) % turtle_backward(dist=10) % turtle_right(angle=90) % turtle_forward(dist=10) % turtle_left(angle=135) % turtle_forward(dist=14) % turtle_left(angle=90) % turtle_forward(dist=14) % turtle_left(angle=135) % turtle_forward(dist=10) % turtle_up() % turtle_right(90) % turtle_forward(dist=10) % turtle_right(angle=90) % turtle_forward(dist=17) % turtle_down() % turtle_left(angle=180) % turtle_forward(dist=34) % turtle_hide() % turtle_left(angle=150) % turtle_forward(dist=20) % turtle_show() % turtle_col(col="green") % turtle_left(angle=60) % turtle_forward(dist=20) % turtle_left(angle=150) % turtle_lty(lty=4) % turtle_forward(dist=17) % turtle_lwd(lwd=3) % turtle_forward(dist=15) % turtle_reset() % turtle_goto(x=10,y=50) % turtle_goto(x=90,y=50) % turtle_reset() % dev.off() % @ \subsection{Advanced Usage of the Package} Now you are familiar with the basics. There are some more advanced ways to use the package. The (\textsf{turtle\_do()}) function is here to wrap calls to multiple plot functions, because it temporarily hides the Turtle while the functions are executed. This results in more efficient plotting. <>= turtle_init() turtle_do({ turtle_move(10) turtle_turn(45) turtle_move(15) }) @ % You may ask why bother using such a function % if the result is the same as while using three separate commands % (in this case this would be \textsf{turtle\_move(10); turtle\_turn(45); turtle\_move(15)}). % The thing is that this function hides the Turtle before evaluating % the expression, thus the time that \textsf{expr} uses is decreased. \clearpage \section{Introduction to \textsf{R}} \subsection{The \textsf{for} loop.} This section illustrates how to connect the functions listed above with the options that \textsf{R} provides us with. For example, sometimes you would like to repeat some action several times. % If it is once or twice then it is easy to type it. But if you wish to use the same % functions for, let's say, 360 times then it turns out to be quite difficult. % Fortunately, \textsf{R} has the tools to deal with it. % In case you want to repeat actions several times In such a case, we can use the \textsf{for} loop. The syntax is as follows: \textsf{for (i in 1:100)\{ expr \}}. Such an expression will evaluate \textsf{expr} 100 times. For example: % \textsf{i} is the counter that counts the turns of the loop. % \textsf{1:100} defines when the counter should start counting % and when it should stop. In % this case the counter \textsf{i} starts in 1 and it increases % by 1 each time the loop turns. % The loop will stop turning when \textsf{i} reaches 100. % Between the curly rackets (\textsf{\{\}}) you write the functions % you would like to repeat, each separated by a new line. For example: <>= turtle_init() turtle_setpos(x=30, y=50) turtle_do({ for(i in 1:180) { turtle_forward(dist=1) turtle_right(angle=2) } }) @ We strongly recommend to call each \textsf{for} loop always within \textsf{turtle\_do()}. \clearpage \subsection{Conditional evaluation} There are some cases when you'd like to call a function provided that some condition is fulfilled. The \textsf{if} expression enables you to do so. The syntax is as follows: \textsf{if (condition) \{ expr \}}. When the \textsf{condition} is fulfilled, the sequence of actions between the curly braces is executed. On the other hand, \textsf{if (condition) \{ exprTRUE \} else \{ exprFALSE \}} evaluates \textsf{exprTRUE} if and only if \texttt{condition} is met and \textsf{exprFALSE} otherwise. Let's study an example. % <>= % turtle_init() % turtle_forward(dist=10) % turtle_right(angle=45) % turtle_forward(dist=15) % dev.off() % @ % % \begin{center} % <>= % cat("\\includegraphics[width=10cm]{", file, "}\n\n", sep="") % @ % \end{center} % % <>== % turtle_init() % turtle_forward(dist=10) % x <- 1 # or e.g. runif(1) - a random number % if (x>0.5) { % turtle_right(angle=45) % turtle_col(col="red") % } % turtle_forward(dist=15) % @ <>= set.seed(5671) turtle_init() turtle_do({ for (i in 1:5) { x <- runif(1) # this function returns a random value between 0 and 1, see ?runif if (x>0.5) { turtle_right(angle=45) turtle_lwd(lwd=1) turtle_col(col="red") } else { turtle_left(angle=45) turtle_lwd(lwd=3) turtle_col(col="purple") } turtle_forward(dist=10) } }) @ As you see, we make some random decisions here. If the condition is fulfilled, so the Turtle turns right and the path is drawn in red. Otherwise, we get a left turn and a purple path. % \noindent % Now each time you call the above synax the result can be different. \clearpage \subsection{Functions} Sometimes it is desirable to ``store'' a sequence of expressions for further use. For example, if you'd like to draw many squares, you can write a custom function so that it can be called many times. For example: <>= turtle_square <- function(r) { for (i in 1:4) { turtle_forward(r) turtle_right(90) } } @ \textsf{turtle\_square} is the name of the function. The parameters of the function are listed within the round brackets (separated by commas). <>= turtle_init() turtle_square(10) turtle_left(90) turtle_forward(30) turtle_square(5) @ \subsection{Recursion} The other thing you should know about is recursion. It is a process of repeating actions in a self-similar pattern. % You have a base case and all the other cases are reduced to the base case % that is defined by some rules (they are called recursive step). % Let's consider a simple example. Your base step is to walk 1 meter % (so you know only how to walk 1 meter). % The recursive step would be walking half way than you have to. % So if your task is to walk, let's say, % 16 meters than by recursion you have to walk 8 meters ( % but you don't do that, you don't know how). % Then by recursion your task is to walk 4 meters. % And again by recursion you have to walk 2 meters. % And now by recursion you have to walk 1 meter. % But you know how to do it! Great! Now you walk 1 meter. % But if you walked 1 meter you can do another one and now you know how % to walk 2 meters. If you know that, % you can walk 2 meters twice and so you can walk 4 meters. % And again you know how to do 4 meters, so you can walk it % again and now you can move by 8 meters. And now you can do % that one more time so you walk the entire 16 meters. % Congratulations you have accomplished the task! Fractals make perfect examples of the power of recursion. Usually, a fractal is an image which at every scale exhibits the same (or very similar) structure. In Section \ref{ex} you have some typical examples of fractals -- the fractal tree, the Koch snowflake and the Sierpi\'{n}ski triangle. \newpage \section{Examples}\label{ex} At the end of this guide we would like to present some colorful and inspiring examples. \subsection{Random lines} The first example generates random lines. <>= set.seed(124) # assure reproducibility turtle_init(100, 100, mode = "cycle") turtle_do({ for (i in 1:10) { turtle_left(runif(1, 0, 360)) turtle_forward(runif(1, 0, 1000)) } }) @ \clearpage \subsection{A spiral} Let's draw some fancy spirals. <>= drawSpiral <- function(lineLen) { if (lineLen > 0) { turtle_forward(lineLen) turtle_right(50) drawSpiral(lineLen-5) } invisible(NULL) # return value: nothing interesting } turtle_init(500, 500, mode="clip") turtle_do({ turtle_setpos(x=0, y=0) turtle_col("blue") drawSpiral(500) turtle_setpos(x=250, y=0) turtle_left(45) turtle_col("green") drawSpiral(354) turtle_setangle(0) }) @ \clearpage \subsection{A rainbow star} <>= turtle_star <- function(intensity=1) { y <- sample(1:657, 360*intensity, replace=TRUE) for (i in 1:(360*intensity)) { turtle_right(90) turtle_col(colors()[y[i]]) x <- sample(1:100,1) turtle_forward(x) turtle_up() turtle_backward(x) turtle_down() turtle_left(90) turtle_forward(1/intensity) turtle_left(1/intensity) } } set.seed(124) turtle_init(500, 500) turtle_do({ turtle_left(90) turtle_star(5) }) @ \clearpage \subsection{Brownian Turtle} This example is inspired by the definition of a Brownian motion. <>= turtle_brownian <- function(steps=100, length=10) { turtle_lwd(2) angles <- sample(c(90,270,180,0), steps,replace=TRUE) coll <- sample(1:657, steps, replace=TRUE) for (i in 1:steps){ turtle_left(angles[i]) turtle_col(colors()[coll[i]]) turtle_forward(length) } } set.seed(124) turtle_init(800, 800, mode="clip") turtle_do(turtle_brownian(1000, length=25)) @ \clearpage \subsection{The Fractal Tree} <>= fractal_tree <- function(s=100, n=2) { if (n <= 1) { turtle_forward(s) turtle_up() turtle_backward(s) turtle_down() } else { turtle_forward(s) a1 <- runif(1, 10, 60) turtle_left(a1) fractal_tree(s*runif(1, 0.25, 1), n-1) turtle_right(a1) a2 <- runif(1, 10, 60) turtle_right(a2) fractal_tree(s*runif(1, 0.25, 1), n-1) turtle_left(a2) turtle_up() turtle_backward(s) turtle_down() } } set.seed(123) turtle_init(500, 600, "clip") turtle_do({ turtle_up() turtle_backward(250) turtle_down() turtle_col("darkgreen") fractal_tree(100, 12) }) @ \clearpage \subsection{The Koch Snowflake} <>= koch <- function(s=50, n=6) { if (n <= 1) turtle_forward(s) else { koch(s/3, n-1) turtle_left(60) koch(s/3, n-1) turtle_right(120) koch(s/3, n-1) turtle_left(60) koch(s/3, n-1) } } turtle_init(600, 400, "error") turtle_do({ turtle_up() turtle_left(90) turtle_forward(250) turtle_right(180) turtle_down() koch(500, 6) }) @ \clearpage \subsection{The Sierpinski Triangle} <>= drawTriangle <- function(points) { turtle_setpos(points[1,1], points[1,2]) turtle_goto(points[2,1], points[2,2]) turtle_goto(points[3,1], points[3,2]) turtle_goto(points[1,1], points[1,2]) } getMid <- function(p1, p2) (p1+p2)*0.5 sierpinski <- function(points, degree){ drawTriangle(points) if (degree > 0) { p1 <- matrix(c(points[1,], getMid(points[1,], points[2,]), getMid(points[1,], points[3,])), nrow=3, byrow=TRUE) sierpinski(p1, degree-1) p2 <- matrix(c(points[2,], getMid(points[1,], points[2,]), getMid(points[2,], points[3,])), nrow=3, byrow=TRUE) sierpinski(p2, degree-1) p3 <- matrix(c(points[3,], getMid(points[3,], points[2,]), getMid(points[1,], points[3,])), nrow=3, byrow=TRUE) sierpinski(p3, degree-1) } invisible(NULL) } turtle_init(520, 500, "clip") turtle_do({ p <- matrix(c(10, 10, 510, 10, 250, 448), nrow=3, byrow=TRUE) turtle_col("red") sierpinski(p, 6) turtle_setpos(250, 448) }) @ \end{document}