<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1177691919768241768</id><updated>2024-10-24T15:51:31.989-07:00</updated><category term="android"/><category term="animations"/><category term="cutscenes"/><category term="gnuplot"/><category term="plot"/><category term="3d"/><category term="affine"/><category term="authentic"/><category term="auto"/><category term="countdown problem"/><category term="dictionaries"/><category term="directx"/><category term="dynamic programming"/><category term="facebook"/><category term="fibonacci"/><category term="haskell"/><category term="higgs"/><category term="keyboard"/><category term="listview"/><category term="mathematica"/><category term="matrix"/><category term="modding"/><category term="opengl"/><category term="optimization"/><category term="particles"/><category term="physics"/><category term="programming"/><category term="rant"/><category term="real-time"/><category term="rotation"/><category term="skills"/><category term="sucks"/><category term="system"/><category term="transformation"/><category term="trees"/><category term="triangle"/><category term="update"/><category term="wolfram"/><title type='text'>Ben&#39;s blog</title><subtitle type='html'>Telling the epic tales of science, programming and life. May quite possibly contain some ranting.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-362387286430853456</id><published>2013-01-26T02:05:00.001-08:00</published><updated>2013-01-26T02:05:44.358-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="auto"/><category scheme="http://www.blogger.com/atom/ns#" term="gnuplot"/><category scheme="http://www.blogger.com/atom/ns#" term="plot"/><category scheme="http://www.blogger.com/atom/ns#" term="real-time"/><category scheme="http://www.blogger.com/atom/ns#" term="update"/><title type='text'>Real-time plot updates using Gnuplot</title><content type='html'>Sometimes it&#39;s very convenient to see real time updates of your gnuplot graphs, for example if you&#39;re doing Monte Carlo simulations or if you have are monitoring stocks. Below I&#39;ll show you the way I do it, by only using gnuplot commands.&lt;br /&gt;
&lt;br /&gt;
First, create a gnuplot configuration file called &#39;&lt;i&gt;loop.plt&lt;/i&gt;&#39;, containing:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;pause 2
replot
reread
&lt;/pre&gt;
Let&#39;s assume we have already given gnuplot the commands to plot something. What this piece of configuration file then does, is wait two seconds, then replot and then reread the &lt;i&gt;loop.plt&lt;/i&gt; file. This will cause these three commands to be executed in an infinite loop. Reread is a very useful command. You can read more about it &lt;a href=&quot;http://www.sunsite.ualberta.ca/Documentation/Gnu/gnuplot-3.7.1/html_node/gnuplot_112.html&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Now, how do we give the first plot command? Well, there are various options. You could for example add the plot command to the &amp;nbsp;&#39;&lt;i&gt;loop.plt&lt;/i&gt;&#39; file (which makes it less portable), but I like to give the instructions through the command line:&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;gnuplot -persist -e &quot;plot &#39;data.dat&#39;&quot; loop.plt&lt;/pre&gt;
where &lt;i&gt;data.dat&lt;/i&gt; is a file that is continuously updated by some process. The nice thing about this is that you can recycle the &#39;&lt;i&gt;loop.plt&lt;/i&gt;&#39; without making any changes to it.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Passing a configuration file&lt;/h3&gt;
&lt;div&gt;
If you have a lot of settings, a better alternative is to let the loop configuration file load your own configuration file. We make the following adjustments:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;load config
pause 2
replot
reread
&lt;/pre&gt;
and we call gnuplot with:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: bash&quot;&gt;gnuplot -persist -e &quot;config=&#39;config.plt&#39;&quot; loop.plt&lt;/pre&gt;
Which sets the variable &lt;i&gt;config&lt;/i&gt; to your own configuration file.
Using this method we have the option to just call &lt;i&gt;gnuplot &#39;config.plt&#39;&lt;/i&gt; to draw the plot once, or use the above command to keep refreshing without having to change any of the files.

If you want to have even more control, you could also make the pause time a variable. See you next time!</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/362387286430853456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2013/01/real-time-plot-updates-using-gnuplot.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/362387286430853456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/362387286430853456'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2013/01/real-time-plot-updates-using-gnuplot.html' title='Real-time plot updates using Gnuplot'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-8026751024860853776</id><published>2012-12-23T08:49:00.001-08:00</published><updated>2012-12-23T08:50:48.449-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="countdown problem"/><category scheme="http://www.blogger.com/atom/ns#" term="haskell"/><category scheme="http://www.blogger.com/atom/ns#" term="trees"/><title type='text'>Solving the Countdown problem in Haskell</title><content type='html'>&lt;h3&gt;
Introduction&lt;/h3&gt;
One of the challenges in the British game show Countdown was to find a way to create a number using other numbers and basic mathematical operators. For example, given the set {2,3,4,5} generate 14, using +, -, *, /. A solution is 5 *4 - 2 * 3. Note that each &amp;nbsp;number should be used exactly once.&lt;br /&gt;
&lt;br /&gt;
An interesting problem is writing an application that lets the computer do all the work for you, so that it finds a solution for a given target number, or maybe even &lt;i&gt;all &lt;/i&gt;the&lt;i&gt;&amp;nbsp;&lt;/i&gt;solutions!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Problem analysis&lt;/h3&gt;
&lt;div&gt;
To find all the ways to combine numbers to yield a certain result we have to generate all the possible ways of &amp;nbsp;combining the numbers (subproblem 1) and then filter out the ones that have our desired result (subproblem 2). But how do we generate all possibilites? What we really want is to generate all the possible valid &lt;u&gt;mathematical expression&lt;/u&gt;s with our numbers. We recognize that these expressions can be written as a tree:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For example, $$5 \cdot 6 - 2 \cdot 3$$:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2WJVcCRcEcgQGlMG8C22RiacXvY35gf29UtGZtX4Eg0x9oGNpqaEW63PJncArdQmU847-I91gzil4bv2qRjhiqy3is6tMzUlSyRhcEUKdi_RsScn65Vjxwfj6nWxdXFwHNpEACc86fiJ3/s1600/tree.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;215&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2WJVcCRcEcgQGlMG8C22RiacXvY35gf29UtGZtX4Eg0x9oGNpqaEW63PJncArdQmU847-I91gzil4bv2qRjhiqy3is6tMzUlSyRhcEUKdi_RsScn65Vjxwfj6nWxdXFwHNpEACc86fiJ3/s320/tree.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Tree representation of mathematical expression&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
Since the operators we have chosen all have two elements, our expressions are binary trees. Thus, this means that&amp;nbsp;our algorithm has to generate all possible trees.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For this task I have chosen Haskell, since it is by far the easiest language to work with trees, as we will soon see. If you are interested in another example why Haskell - or other functional languages - are very convenient to work with if you have trees, check out my fully fledged &amp;nbsp;&lt;a href=&quot;https://github.com/benruijl/spl&quot;&gt;spl compiler&lt;/a&gt;. This project is a compiler for a custom programming language, written in Haskell in only 900 lines! I have written my own parser, abstract syntax tree and Intel backend using the same techniques you&#39;ll see below. If you are interested in this project, let me know, and I may write a tutorial on this.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Implementation&lt;/h3&gt;
&lt;div&gt;
First, we have to define the grammar of our mathematical expressions:&lt;/div&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;data Exp = Num Int | Plus Exp Exp | Sub Exp Exp | Mul Exp Exp | Div Exp Exp deriving Eq
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;
Our expression is defined as being a number, or any of our binary operators. The elements (branches) of each operator are mathematical expressions themselves as well.&amp;nbsp;You can immediately see that this recursive definition of a tree structure is much, much smaller than it would have been in for example Java or C.&lt;br /&gt;
&lt;br /&gt;
In an object oriented language the solution for such a structure would be to make a base class Exp, that has 5 subclasses. Each subclass then has two variables of type Exp, except for the Num subclass which has an integer variable.&lt;br /&gt;
&lt;br /&gt;
Before moving to the main algorithm, I&#39;ll show some code for convenience functions. The first implements a Show function for our custom data type, making a tree easier to read:&lt;br /&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;instance Show Exp where
 show (Num n) = show n
 show (Plus a b) = &quot;(&quot; ++ show a ++ &quot;+&quot; ++ show b ++ &quot;)&quot;
 show (Sub a b) = &quot;(&quot; ++ show a ++ &quot;-&quot; ++ show b ++ &quot;)&quot;
 show (Mul a b) = &quot;(&quot; ++ show a ++ &quot;*&quot; ++ show b ++ &quot;)&quot;
 show (Div a b) = &quot;(&quot; ++ show a ++ &quot;/&quot; ++ show b ++ &quot;)&quot;
&lt;/pre&gt;
&lt;br /&gt;
If you now type&lt;br /&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;show (Plus (Num 5) (Mul (Num 6) (Num 2)))&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
in the Haskell interpreter, the result would be&lt;i&gt; (5 + (6 * 2))&lt;/i&gt;. In the code above you can see &lt;i&gt;pattern matching&lt;/i&gt;. If you are not familiar with functional languages, you can read about this feature &lt;a href=&quot;http://en.wikibooks.org/wiki/Haskell/Pattern_matching&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
We also need a function that actually calculates the result of our abstract expression. Using pattern matching again:&lt;br /&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;reduce :: Exp -&amp;gt; Int
reduce (Num n) = n
reduce (Plus a b) = reduce a + reduce b
reduce (Sub a b) = reduce a - reduce b
reduce (Mul a b) = reduce a * reduce b
reduce (Div a b) = reduce a `div` reduce b
&lt;/pre&gt;
&lt;br /&gt;
Now we can think about the algorithm itself. We want to use all the numbers and use them only once, so we have to generate all the possible ways to select an element from a list and also keep track of which items we have not used yet. That&#39;s what the following function is for:&lt;br /&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;-- list should have at least 2 elements
split :: [a] -&amp;gt; [a] -&amp;gt; [(a, [a])]
split [] _ = []
split (x:xs) acc = [(x, acc ++ xs)] ++ (split xs (acc ++ [x]))
&lt;/pre&gt;
Split turns a list [1,2,3] into [(1, [2,3]), (2,[1,3]), (3, [1,2]). Thus, when we select a binary operator, we use the first number of the tuple as its left branch and we can use the list of remaining number to generate a subtree for the right branch:&lt;br /&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;pos :: [Int]-&amp;gt; [Exp]
pos [n] = [Num n] -- one number left? no binary operators possible
pos n = concatMap allpos subtree
 where
 subtree = map (\(a,r) -&amp;gt; (Num a, pos r)) (split n [])
 allpos (a,b) = concatMap (\e -&amp;gt; pos&#39; a e) b
 pos&#39; a b = [Plus a b, Sub a b, Sub b a, Mul a b, Div a b, Div b a]
&lt;/pre&gt;
Let&#39;s look at the &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;subtree&lt;/span&gt; function first. This generates all possible subtrees where the left branch is a given number. The function &lt;i&gt;pos&#39;&lt;/i&gt; gives all the possible binary operators where &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;a&lt;/span&gt; and &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;b&lt;/span&gt; are branches. As you can see, for the subtraction and division operator, the left and right branches interchanged is also a valid option. That&#39;s because 1 - 2 != 2 - 1.

&lt;br /&gt;
&lt;br /&gt;
Finally, the&amp;nbsp;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;allpos&lt;/span&gt; function generates puts all these possiblities in a list. Of course, some of these expressions may be invalid due to the rules of the game. For example, it&#39;s not allowed to have a negative value or a fractional values in any of the subresults. Another thing that should be filtered is duplicates: 1 + 2 is the same expression as 2 + 1, so it should appear only once. That&#39;s why we have the following filter function:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;-- remove illegal attempts and attempts that are the same
valid :: Exp -&amp;gt; Bool
valid (Num n) = True
valid (Plus a b) = valid a &amp;amp;&amp;amp; valid b &amp;amp;&amp;amp; reduce a &amp;gt; reduce b -- only allow one
valid (Sub a b) = valid a &amp;amp;&amp;amp; valid b &amp;amp;&amp;amp; reduce a - reduce b &amp;gt;= 0 -- subsolutions should be positive
valid (Mul a b) = valid a &amp;amp;&amp;amp; valid b &amp;amp;&amp;amp; reduce a &amp;gt; reduce b
valid (Div a b) = valid a &amp;amp;&amp;amp; valid b &amp;amp;&amp;amp; reduce b &amp;gt; 0 &amp;amp;&amp;amp; reduce a `mod` reduce b == 0
&lt;/pre&gt;
And finally we have a function that receives a list of numbers and the target number as input and that returns all the possible expressions:
&lt;br /&gt;
&lt;pre class=&quot;brush:haskell&quot;&gt;findVal :: [Int] -&amp;gt; Int -&amp;gt; [Exp]
findVal n res = filter (\e -&amp;gt; valid e &amp;amp;&amp;amp; reduce e == res) (pos n)
&lt;/pre&gt;
&lt;br /&gt;
And that&#39;s the solution to the problem!&amp;nbsp;If you run this application, you will see that contrary to what you may expect, very little memory is used. This is because Haskell does &lt;i&gt;lazy evaluation&lt;/i&gt;, so the lists are actually not computed beforehand but each element is evaluated one at a time.&lt;br /&gt;
&lt;br /&gt;
There are some optimzations, which I leave as an exercise for the reader: for example, you can reject wrong expressions much earlier. If you generate a binary operator with two numbers, say&amp;nbsp;&lt;i&gt;Plus (Num 2) (Num 4)&lt;/i&gt;, you can reject it immediately (because we only allow 4 + 2 and not 2 + 4).&lt;br /&gt;
&lt;br /&gt;
And that&#39;s it for today. I hope you&#39;ve learned something new and interesting :)
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/8026751024860853776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2012/12/solving-countdown-problem-in-haskell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/8026751024860853776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/8026751024860853776'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2012/12/solving-countdown-problem-in-haskell.html' title='Solving the Countdown problem in Haskell'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2WJVcCRcEcgQGlMG8C22RiacXvY35gf29UtGZtX4Eg0x9oGNpqaEW63PJncArdQmU847-I91gzil4bv2qRjhiqy3is6tMzUlSyRhcEUKdi_RsScn65Vjxwfj6nWxdXFwHNpEACc86fiJ3/s72-c/tree.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-7693005396437652686</id><published>2012-07-18T08:41:00.002-07:00</published><updated>2012-12-23T03:36:33.662-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3d"/><category scheme="http://www.blogger.com/atom/ns#" term="gnuplot"/><category scheme="http://www.blogger.com/atom/ns#" term="mathematica"/><category scheme="http://www.blogger.com/atom/ns#" term="plot"/><category scheme="http://www.blogger.com/atom/ns#" term="wolfram"/><title type='text'>Making gnuplot plots look like Mathematica plots</title><content type='html'>For an article I am writing I wanted to plot the following function: &amp;nbsp;$$
 \theta \left(x &amp;gt; \frac{1}{2} \right) \left(\sin(4 \pi x) + \sin(4 \pi y) +2 \right)
$$&lt;br /&gt;
Wolfram Alpha gives the following pretty plot:&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRHEYFeYxmq2xTOdBA5grdsRM_IKip6-HL3HQ81Jyc-mgvIuT30j8QTcrfC2ykeKxyYbmCVzhDN9BfVZTmPQb9j_uNwYhsChj73jD30HOT_uEmhYGGd0YAdmBsJ3lv3a_ufIGa5tZsQrSP/s1600/wolfram.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRHEYFeYxmq2xTOdBA5grdsRM_IKip6-HL3HQ81Jyc-mgvIuT30j8QTcrfC2ykeKxyYbmCVzhDN9BfVZTmPQb9j_uNwYhsChj73jD30HOT_uEmhYGGd0YAdmBsJ3lv3a_ufIGa5tZsQrSP/s1600/wolfram.gif&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Plot from Wolfram Alpha&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
However, since you need to pay now to export this picture in a more usable format (like svg, eps or pdf) I decided to recreate the picture in gnuplot. Friendly advice for you others writing articles: &lt;b&gt;always&lt;/b&gt; use vector formats where possible, otherwise your graphics will look horrible on higher resolutions!&lt;br /&gt;
&lt;br /&gt;
To plot the function in gnuplot we first have to do a little trick, because the step function is not included in gnuplot. It does have the sign function, however. So we can do the following:

$$
 \theta(x &amp;gt; \frac{1}{2}) = \frac{1 + \text{sgn}(x-\frac{1}{2})}{2}
$$&lt;br /&gt;
A first attempt, with default settings is:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:bash&quot;&gt;set terminal postscript eps
set pm3d at s hidden3d
unset hidden3d
unset surface
set xrange [0:1]
set yrange [0:1]
set samples 20,20

splot (1+sgn(x-0.5))*(sin(4*pi*x) + sin(4*pi*y)+2)/2 title &#39;&#39;
&lt;/pre&gt;
&lt;br /&gt;
This gives

&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-uci2PGmt-X1p84_pH9ywO0eN9sZtfN_d-6hoBmVdLoJVTGjB73ei_b0fZ6UuFLyjHtv0vnGo55Vudodea_tm1CSVnm_hrQ-D4SrpQhrgvwXHYdVzboXVXkXhjuhDkRBdLDNUjAvvx2Fu/s1600/attempt1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;160&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-uci2PGmt-X1p84_pH9ywO0eN9sZtfN_d-6hoBmVdLoJVTGjB73ei_b0fZ6UuFLyjHtv0vnGo55Vudodea_tm1CSVnm_hrQ-D4SrpQhrgvwXHYdVzboXVXkXhjuhDkRBdLDNUjAvvx2Fu/s320/attempt1.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
This doesn&#39;t really look too good. First thing that has to be changed is the color palette and the color of the grid. The color palette can be changed like this:

&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:bash&quot;&gt;set terminal postscript eps
set palette defined ( 0 &quot;#bd2c29&quot;, 2 &quot;#ffd35a&quot;, 6 &quot;white&quot;)
&lt;/pre&gt;
&lt;br /&gt;
The numbers in front of the color codes are the values of the function that the color should correspond to. Thankfully, gnuplot automatically interpolates the colors.&lt;br /&gt;
&lt;br /&gt;
Next up is the grid color. The color can be set to a given line style by adding the style number at the end of the pm3d options:

&lt;br /&gt;
&lt;pre class=&quot;brush:bash&quot;&gt;set pm3d implicit at s hidden3d 100
set style line 100 lc rgb &#39;#000000&#39; lt 1 lw 0.6&lt;/pre&gt;
&lt;br /&gt;
Here I have defined the grid style to be a thin black line. I have chosen index 100 to make sure it doesn&#39;t clash with other settings.&lt;br /&gt;
&lt;br /&gt;
After removing the color bar and shifting the image down with ticslevel, we get the final image:
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQFbGB14dz5JFZKAtyqsS7JAsoo7XIwpCCeWLOKdIpFTHjNxfsuBs-dn9e4ejbcpTXTsIwT_96knhcw31MEFQaCeZBF6kpBgFfbasnwg29X-co1s69Y7tINOLhp8S5XLkdHEp2j0A1HoPL/s1600/final.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;206&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQFbGB14dz5JFZKAtyqsS7JAsoo7XIwpCCeWLOKdIpFTHjNxfsuBs-dn9e4ejbcpTXTsIwT_96knhcw31MEFQaCeZBF6kpBgFfbasnwg29X-co1s69Y7tINOLhp8S5XLkdHEp2j0A1HoPL/s320/final.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
This looks a lot better! The only thing missing is the shadowing of surfaces angled away from the camera. I am not aware of a way to produce these in gnuplot. If anyone has additional advice to improve the plot, please let me know!&lt;br /&gt;
&lt;br /&gt;
The final version of the code:

&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:bash&quot;&gt;set terminal postscript eps
set output &#39;| epstopdf --filter --outfile=plot.pdf&#39;
set palette defined ( 0 &quot;#bd2c29&quot;, 2 &quot;#ffd35a&quot;, 6 &quot;white&quot;)
set pm3d implicit at s hidden3d 100
set style line 100 lc rgb &#39;#000000&#39; lt 1 lw 0.6
unset hidden3d
unset surface
set border 4095 front linetype -1 linewidth 0.8
set ticslevel 0
set xrange [0:1]
set yrange [0:1]
set ztics 1
set isosamples 40,40
set samples 20,20
unset colorbox

splot (1+sgn(x-0.5))*(sin(4*pi*x) + sin(4*pi*y)+2)/2 title &#39;&#39;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/7693005396437652686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2012/07/making-gnuplot-plots-look-like.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/7693005396437652686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/7693005396437652686'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2012/07/making-gnuplot-plots-look-like.html' title='Making gnuplot plots look like Mathematica plots'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRHEYFeYxmq2xTOdBA5grdsRM_IKip6-HL3HQ81Jyc-mgvIuT30j8QTcrfC2ykeKxyYbmCVzhDN9BfVZTmPQb9j_uNwYhsChj73jD30HOT_uEmhYGGd0YAdmBsJ3lv3a_ufIGa5tZsQrSP/s72-c/wolfram.gif" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-6173384651868134447</id><published>2012-07-04T03:10:00.000-07:00</published><updated>2012-07-04T04:22:45.134-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="higgs"/><category scheme="http://www.blogger.com/atom/ns#" term="particles"/><category scheme="http://www.blogger.com/atom/ns#" term="physics"/><title type='text'>What is the Higgs boson?</title><content type='html'>Today the Higgs boson has been found at CERN, a great accomplishment in the field of theoretical particle physics. This discovery means that the model we are currently using is completed: the final ingredient has been found. This model, called the Standard Model, yields very good predictions of what is happening in nature.&lt;br /&gt;
&lt;br /&gt;
But what is this Higgs boson, what does it do and why didn&#39;t we see it before?&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;





The mystery of the massive particles&lt;/h2&gt;
&lt;div&gt;
When physicists were deriving the physics of elementary particles, they used certain assumptions about the universe, most of them are related to symmetries. What&#39;s a symmetry? Take for example rotational symmetry. Imagine you are standing in the middle of a round football stadium. It does not matter if you rotate, you will still see the same image. There is a very fancy theorem that says that every symmetry has an accompanied conserved quantity. The rotational symmetry, for example, yields conservation of angular momentum, whereas translational symmetry in time (meaning physics looks the same now and 10 minutes from now) yield conservation of energy.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;Using some more advaced symmetry groups all of our beloved standard particles can be found:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Standard_Model_of_Elementary_Particles.svg/556px-Standard_Model_of_Elementary_Particles.svg.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Standard_Model_of_Elementary_Particles.svg/556px-Standard_Model_of_Elementary_Particles.svg.png&quot; width=&quot;297&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
The standard model (without Higgs)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
The group in red are called gauge bosons. They are resultants of a very special symmetry and they can be interpreted as &lt;i&gt;forces &lt;/i&gt;working on all the other particles. In fact, every elementary force has a matching gague boson. The photon (symbolised with a gamma), or &quot;light&quot;, transfers electromagnetic forces, the gluon the strong force and Z and W the weak force.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
But there is a problem. The theory requires the W and Z boson to be &lt;i&gt;massless&lt;/i&gt;&amp;nbsp;in order for the theory to work. This is obviously not the case, because these particles have been found to have mass. In fact, they are pretty heavy!&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;





The Higgs mechanism&lt;/h2&gt;
&lt;div&gt;
When physicist discovered that the theory was in trouble, they started searching for solutions. The symmetry of nature that can be used to find the gauge bosons worked far too good to just abandon it. Then, a new idea rose: we keep the symmetry, but we say nature&amp;nbsp;&lt;i&gt;broke&lt;/i&gt; it spontaneously. Wait, what?&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
How does this work? Imagine you have a piece of plastic between your fingers and you apply a little pressure to it. Initially, the plastic stick is straight, even when you apply a little pressure to it. Now the system (nature) has a symmetry: there is for example rotational symmetry if you are standing at the position of the rod (if you ignore the hand).&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
But remember the hand was applying a force? This means that the stick could spontaneously jump to either the left or the right, as can be seen in the picture (try this at home ;) ). Now the symmetry that nature had is broken, spontaneously and without external help. Note that in the analogy, the hand should be seen as an initial energy that the universe has.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtjcR_8QnDHA7e4XfJUU7hwh2GF581in2dDPXTvrIldlEYzhD0NuVkA2aq3_CZYwcOa-1g3VcCBH_s-FuIeDufBKdtQRwCUsFVwDbpQGJmed57m3VgC-JY2d5IGNf4OVq6zmP4AI9GX2rz/s1600/strip.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;296&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtjcR_8QnDHA7e4XfJUU7hwh2GF581in2dDPXTvrIldlEYzhD0NuVkA2aq3_CZYwcOa-1g3VcCBH_s-FuIeDufBKdtQRwCUsFVwDbpQGJmed57m3VgC-JY2d5IGNf4OVq6zmP4AI9GX2rz/s320/strip.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
Spontaneous symmetry breaking&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
A similar scenario this of a toy car that is sitting on a small mountain, but it has some energy which makes the car shift a little. Given enough time, the car will roll off the mountain into a valley, where it will remain.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Mexican_hat_potential_polar.svg/600px-Mexican_hat_potential_polar.svg.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;256&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/7/7b/Mexican_hat_potential_polar.svg/600px-Mexican_hat_potential_polar.svg.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;Imagine a toy car in this figure&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now, it turns out that breaking this symmetry can be done by introducing a particle: the Higgs particle. When analysing the properties of this particle, it turns out that this particle interacts with all the other particles, including itself! Due to these interactions, the particles gain mass.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;




Why did this take so long to find?&lt;/h2&gt;
&lt;div&gt;
Well, we didn&#39;t know where to look. Basically, in the LHC particles are shot at eachother with incredible speeds, and thus incredibly high energies. Since E=mc^2, it takes very high energies to create particles with high mass. The problem is, we don&#39;t know the mass of the Higgs, it is a free parameter of the theory. This means the mass is not predicted by the theory. And because of that, the whole LHC range has to be explored (with no guarantee that the Higgs boson is actually in this range).&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;Complications arise due to the fact the Higgs particle decays intoa lot of other particles very, very quickly. So we can actually only see the remnants of the Higgs particle. When there is enough energy to create a Higgs, we&#39;d expect to see more of these remnants: a peak in a graph.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;Today, the people at CERN announced that the peaks they found in many expirements, are trustworthy enough to say that the Higgs particle has been found at about 126 GeV. This is great news, because now we can confidently continue the search for theories that expand the standard model, like supersymmetry and other theories that may introduce gravity into the picture.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;background-color: white;&quot;&gt;We aren&#39;t quite there yet, but a theory of everything is coming!&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span id=&quot;goog_369349579&quot;&gt;&lt;/span&gt;&lt;span id=&quot;goog_369349580&quot;&gt;&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/6173384651868134447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2012/07/what-is-higgs-boson.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/6173384651868134447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/6173384651868134447'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2012/07/what-is-higgs-boson.html' title='What is the Higgs boson?'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtjcR_8QnDHA7e4XfJUU7hwh2GF581in2dDPXTvrIldlEYzhD0NuVkA2aq3_CZYwcOa-1g3VcCBH_s-FuIeDufBKdtQRwCUsFVwDbpQGJmed57m3VgC-JY2d5IGNf4OVq6zmP4AI9GX2rz/s72-c/strip.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-1952610381083227409</id><published>2011-11-26T01:37:00.000-08:00</published><updated>2011-11-26T04:04:19.587-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="affine"/><category scheme="http://www.blogger.com/atom/ns#" term="directx"/><category scheme="http://www.blogger.com/atom/ns#" term="matrix"/><category scheme="http://www.blogger.com/atom/ns#" term="opengl"/><category scheme="http://www.blogger.com/atom/ns#" term="rotation"/><category scheme="http://www.blogger.com/atom/ns#" term="transformation"/><title type='text'>Affine transformations and their inverse</title><content type='html'>When you&#39;re programming games or other 3d applications using OpenGL or DirectX, it is often required to use affine transformation matrices to describe transformations in space (4x4 matrices and the like). There is not a lot of documentation about this online, and most implementations I&#39;ve seen, have some sort of hack. In this tutorial, I&#39;ll describe what affine transformations are, and more importantly, how to invert them correctly and efficiently.

It is assumed that the reader knows what a matrices are and how to multiply them.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The affine transformation&lt;/b&gt;&lt;br /&gt;
Imagine you have a ball lying at (1,0) in your coordinate system. You want to move this ball to (0,2) by first rotating the ball 90 degrees to (0,1) and then moving it upwards with 1. This transformation is described by a rotation and translation. The rotation is:

$$
  \left[\begin{array}{cc}
   0 &amp;amp; -1\\
   1 &amp;amp; 0\\
  \end{array}\right]
$$
and the translation is (0,1).

To apply this transformation to a vector $\vec{x}$, we do:

$$\vec{x}^\prime = R \vec{x} + \vec{T}$$

where R is a rotation matrix, and T is a translation vector. This is called an &lt;i&gt;affine transformation&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
If you&#39;re in 2d space, there is no 2x2 matrix that will do this transformation for all points. However, if we go one dimension higher, to a 3x3 matrix, you can! That&#39;s why OpenGL uses 4x4 matrices to describe 3d transformations, as we&#39;ll see later.&amp;nbsp;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The matrix representation&lt;/b&gt;&lt;br /&gt;
The best way to explain how to make this matrix, is to give the matrix for the example above.&lt;br /&gt;
&lt;br /&gt;
$$
  \left[\begin{array}{ccc}
   0 &amp;amp; -1 &amp;amp; 0 \\
   1 &amp;amp; 0 &amp;amp; 1 \\
   0 &amp;amp; 0 &amp;amp; 1 \\
  \end{array}\right] &amp;nbsp;$$&lt;br /&gt;
&lt;br /&gt;
As you can see, the left upper block is the rotation matrix, and to the right going downwards we have our translation. Because it&#39;s a 3x3 matrix now, we have to apply it to a 3d vector. We take the vector we had, $(1,0)$, and set the third component to 1. See what happens:&lt;br /&gt;
&lt;br /&gt;
$$ \left[\begin{array}{ccc} 0 &amp;amp; -1 &amp;amp; 0 \\ 1 &amp;amp; 0 &amp;amp; 1 \\ 0 &amp;amp; 0 &amp;amp; 1 \\ \end{array}\right] 
\begin{pmatrix} 1\\0\\1 \end{pmatrix} = \begin{pmatrix} 0\\2\\1 \end{pmatrix} $$&lt;br /&gt;
&lt;br /&gt;
This gives the result we wanted! If you look closer to the matrix multiplication, we see why this works. The trick is to set the last component of the vector to 1, so that the translation just gets added. In a short-hand notation the matrix and vector look like this:&lt;br /&gt;
&lt;br /&gt;
$$ \left[\begin{array}{c|c} R &amp;amp; T \\ \hline 0 &amp;amp; 1 \\ \end{array}\right] \begin{pmatrix} x\\ \hline 1 \end{pmatrix}=\begin{pmatrix} x^\prime\\ \hline 1 \end{pmatrix}$$&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Inverting an affine transformation matrix&lt;/b&gt;&lt;br /&gt;
Sometimes it is very imporant to invert an affine transformation, for example to transform back from world space to object space. A naive approach is to just write a function that inverts 3x3 or 4x4 matrices. This is very inefficient, &amp;nbsp;because there are some nice properties we can use.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If we think about what happens when we apply the affine transformation matrix, we rotate first over an angle $\alpha$, and then translate over $(T_x, T_y)$. So the inverse should translate first with $(-T_x, -T_y)$, and then rotate over&amp;nbsp;$-\alpha$. Unfortunately, that&#39;s not what happens. What does happen is that the rotation is always applied first. So we have to correct for that by modifying our translation. A derivation:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\begin{array}&lt;br /&gt;
\vec{x}^\prime = R\vec{x} + T \\&lt;br /&gt;
\vec{x}^\prime - T = R\vec{x} \\&lt;br /&gt;
R^{-1}(\vec{x}^\prime - T) = \vec{x}\\&lt;br /&gt;
\end{array}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
So to get back the original vector $\vec{x}$, we have a new affine transformation:&lt;br /&gt;
&lt;br /&gt;
$$ \vec{x} =&amp;nbsp;R^{-1}\vec{x}^\prime &amp;nbsp;- (R^{-1}T) $$&lt;br /&gt;
&lt;br /&gt;
What we have to do now is calculate the inverse of a rotation matrix and using that result, calculate our new translation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#39;s recall how a general rotation matrix in 2d looks like:&lt;br /&gt;
&lt;br /&gt;
$$ \left[\begin{array}{cc} \cos(\alpha) &amp;amp; - \sin(\alpha) \\ \sin(\alpha) &amp;amp; \cos(\alpha) \\ \end{array}\right] $$&lt;br /&gt;
&lt;br /&gt;
Because a rotation matrix is unitary, the inverse of a rotation matrix is equal to its transpose, so inverting can be done very quickly:&lt;br /&gt;
&lt;br /&gt;
$$ \left[\begin{array}{cc} \cos(\alpha) &amp;amp; \sin(\alpha) \\ -\sin(\alpha) &amp;amp; \cos(\alpha) \\ \end{array}\right] $$&lt;br /&gt;
&lt;br /&gt;
Now all we have to do is apply this to T, to get all the components for our inverse matrix:&lt;br /&gt;
&lt;br /&gt;
$$ \left[\begin{array}{c|c} R^{-1} &amp;amp; R^{-1}T \\ \hline 0 &amp;amp; 1 \\ \end{array}\right] \begin{pmatrix} x^\prime\\ \hline 1 \end{pmatrix}$$&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Putting it together&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
As we&#39;ve seen, general 2d affine transformation matrices look like&lt;br /&gt;
&lt;br /&gt;
$$ \left[\begin{array}{ccc} \cos(\alpha) &amp;amp; - \sin(\alpha) &amp;amp; T_x \\ \sin(\alpha) &amp;amp; \cos(\alpha) &amp;amp; T_y \\ 0 &amp;amp; 0 &amp;amp; 1 \\ \end{array}\right] $$&lt;br /&gt;
&lt;br /&gt;
Applying the strategy we&#39;ve derived above, the inverse is:&lt;br /&gt;
&lt;br /&gt;
$$ \left[\begin{array}{ccc} \cos(\alpha) &amp;amp; \sin(\alpha) &amp;amp; -T_x \cos(\alpha) - T_y \sin(\alpha) \\ -\sin(\alpha) &amp;amp; \cos(\alpha) &amp;amp; -T_y \cos(\alpha) + T_x \sin(\alpha) \\ 0 &amp;amp; 0 &amp;amp; 1 \\ \end{array}\right] $$&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Expanding to 3d is trivial, since the same rules hold. For example, let&#39;s pick the rotation of $\theta$ over the axis $(0,1,0)$ and a translation $(1,2,3)$.&lt;br /&gt;
&lt;br /&gt;
The matrix becomes:&lt;br /&gt;
$$ \left[\begin{array}{cccc} \cos(\theta) &amp;amp; 0 &amp;amp; &amp;nbsp;\sin(\theta) &amp;amp;1 \\ 0 &amp;amp; 1 &amp;amp; 0 &amp;amp; 2\\ -\sin(\theta) &amp;amp; 0 &amp;amp; \cos(\theta) &amp;amp; 3 \\ 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 \\ \end{array}\right] $$&lt;br /&gt;
&lt;br /&gt;
And the inverse is:&lt;br /&gt;
$$&lt;br /&gt;
\left[&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
\begin{array}{cccc}&lt;br /&gt;
&amp;nbsp;\cos (\theta ) &amp;amp; 0 &amp;amp; -\sin (\theta ) &amp;amp; 3 \sin (\theta )-\cos (\theta ) \\&lt;br /&gt;
&amp;nbsp;0 &amp;amp; 1 &amp;amp; 0 &amp;amp; -2 \\&lt;br /&gt;
&amp;nbsp;\sin (\theta ) &amp;amp; 0 &amp;amp; \cos (\theta ) &amp;amp; -3 \cos (\theta )-\sin (\theta ) \\&lt;br /&gt;
&amp;nbsp;0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1&lt;br /&gt;
\end{array}&lt;br /&gt;
&lt;br /&gt;
\right]&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
These 4x4 matrices are the ones that OpenGL expects in functions like&amp;nbsp;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: monospace;&quot;&gt;glMultMatrixf!&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In order to use this knowledge in your code, you should write a matrix class that can 1)&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle&quot;&gt;create a rotation matrix from an angle and axis&lt;/a&gt;&amp;nbsp;2)&amp;nbsp;transpose a matrix and 3) be applied to a vector.&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
Hopefully this tutorial has helped you better grasp the concepts of affine transformations. We&#39;ve seen the definition of these transformations and how to use those to find a shortcut for a quick inversion algorithm. If you have any questions, please let me know!</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/1952610381083227409/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/11/affine-transformations-and-their.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/1952610381083227409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/1952610381083227409'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/11/affine-transformations-and-their.html' title='Affine transformations and their inverse'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-390603661094774740</id><published>2011-11-01T07:28:00.000-07:00</published><updated>2011-11-03T04:31:55.953-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="authentic"/><category scheme="http://www.blogger.com/atom/ns#" term="facebook"/><category scheme="http://www.blogger.com/atom/ns#" term="rant"/><category scheme="http://www.blogger.com/atom/ns#" term="sucks"/><category scheme="http://www.blogger.com/atom/ns#" term="system"/><title type='text'>Facebook blacklisted me...</title><content type='html'>For a website I am building I want to have facebook authentication, which means that users don&#39;t have to make an account. In order to use their API, facebook &lt;b&gt;forces&lt;/b&gt; you to make an actual profile on their website. With great reluctance, I made my profile page, getting flooded with requests and other messages instantly.  Well, I thought, this is what I have to do to get my key. So then I went to the app registration page and I got the following message:  &lt;br /&gt;
&lt;blockquote&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;color: red;&quot;&gt;You can no longer create apps because our systems indicated that your account may not be authentic. Facebook requires users to provide their real first and last names, and fake accounts are a violation of our Statement of Rights and Responsibilities (SRR 4.1), even when used to host or test apps. Also note that maintaining multiple accounts, even if they are authentic, is also prohibited. If you would like to create a test user to test app functionality, you can do so here: http://developers.facebook.com/docs/test_users/.   If you believe you have received this message in error, please submit an appeal: https://www.facebook.com/help/contact_us.php?id=140703502680919.&lt;/span&gt;&lt;/blockquote&gt;Seriously, WTF. After all that trouble I went through, their &quot;systems&quot; say my account is not authentic. What does that even mean, their systems? This completely baffles me, since I have dumped all sorts of personal stuff on there and I went through an SMS authentication. Nonetheless, their &quot;systems&quot; think I am lying.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;I am pretty pissed off right now. The API key proved to be one big carrot on a stick to lure me in. Now I have to scan government papers to actually prove I am who I am.  If their oh so intelligent system doesn&#39;t think my passport is a fake, that is...&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;update&lt;/b&gt;: I have sent a heavily censored copy of my driver&#39;s license to facebook. I am un-blacklisted now.</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/390603661094774740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/11/facebook-blacklisted-me-wtf.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/390603661094774740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/390603661094774740'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/11/facebook-blacklisted-me-wtf.html' title='Facebook blacklisted me...'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-8774240522428430510</id><published>2011-10-31T05:25:00.000-07:00</published><updated>2013-01-27T05:11:32.182-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="dynamic programming"/><category scheme="http://www.blogger.com/atom/ns#" term="fibonacci"/><category scheme="http://www.blogger.com/atom/ns#" term="optimization"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="skills"/><category scheme="http://www.blogger.com/atom/ns#" term="triangle"/><title type='text'>Skills every programmer should have #1: Dynamic programming</title><content type='html'>During this course I&#39;ll try and describe several techniques and skills that every programming should have. Many of these subjects involve concepts that save a lot of time and provide easier solutions to problems than ad-hoc ones. If you have any suggestions, please let me know!

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;



Dynamic programming&lt;/h3&gt;
Dynamic programming is the first skill that every programmer should have. It can be used when you have a problem that can be split up into sub-problems that you&#39;ve already calculated and cached. I have used it in numerous situations, including optimal control theory problems and &lt;a href=&quot;http://projecteuler.net/&quot;&gt;Project Euler&lt;/a&gt; problems.

 An example:&lt;br /&gt;
&lt;br /&gt;
Imagine you want to write an application that prints the factorial for every number up to N, so:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;0! 1! 2! 3! ... N!
&lt;/pre&gt;
&lt;br /&gt;
A naive solution would be
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class Main {
 public static long fac(int n) {
  if (n &amp;lt;= 1) {
   return 1;
  }

  return n * fac(n - 1);
 }

 public static void main(String[] args) {
  for (int i = 0; i &amp;lt; 10; i++) {
   System.out.println(fac(i));
  }
 }
}
&lt;/pre&gt;
This becomes very slow if N is large (in this example you can&#39;t make N too large, because the long overflows very quickly. Use BigInteger instead). However, if we look at the factorial function, we see that if we calculate 10!, we&#39;re recalculating 9!. We see that 10! = 10 * 9!. In general:

&lt;br /&gt;
&lt;pre&gt;N! = N * (N-1)!
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
If we were to cache n! in a map, we&#39;d be able to significantly reduce computation time. An improved solution:

&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class Main {
 static Map&amp;lt;Integer, Long&amp;gt; facs = new HashMap&amp;lt;Integer, Long&amp;gt;();

 public static long fac(int n) {
  if (facs.containsKey(n)) {
   return facs.get(n);
  }
  
  if (n &amp;lt;= 1) {
   return 1;
  }

  long result = n * fac(n - 1);
  /* Add factorial to map. */
  facs.put(n, result);
  
  return result;
 }

 public static void main(String[] args) {

  for (int i = 1; i &amp;lt; 10; i++) {
   System.out.println(fac(i));
  }
 }
}
&lt;/pre&gt;
This is what&#39;s called &lt;b&gt;dynamic programming&lt;/b&gt; and it is very useful to make seemingly infeasable solutions possible in exchange for memory. Let&#39;s look at a realistic example.

&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;



Best path in a triangle&lt;/h3&gt;
Imagine you have a triangle like this:

&lt;br /&gt;
&lt;pre&gt;   3
  7 4
 2 4 6
8 5 9 3
&lt;/pre&gt;
and you&#39;re aked to calculate the path with the optimal score. The score is calculated by adding all the numbers you go through. In this case the optimal score is 3 + 7 + 4 + 9 = 23. Note that this is &lt;a href=&quot;http://projecteuler.net/problem=67&quot;&gt;problem 67&lt;/a&gt; of the Euler Project, so if you want to try it for yourself first, you should stop reading here!&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;This problem is easy to solve for small triangles, but for big triangles it becomes infeasable to calculate all the routes. We&#39;re now going to look at a triangle with a depth of 100. This means that there are 2^99 routes! Looking at the triangle above, we see that the value at the top is 3 + [the maximum of the subtree 7 and subtree 4].&lt;br /&gt;
&lt;br /&gt;
This looks like a division into subproblems!

If we were to cache the values of the tree at 7 and 4, we&#39;d know the value at the top incredibly fast. The dynamic programming solution is thus as follows:

&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class Main {
 /* Values at every point in the tree. */
 public static Map&amp;lt;Point, Integer&amp;gt; values;
 public static List&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; tree;
 
 public static Integer getValue(Point p) {
  /* Check cache first. */
  if (values.containsKey(p)) {
   return values.get(p);
  }
  
  /* Boundary conditions. */
  if (p.y == tree.size() - 1) {
   return tree.get(p.y).get(p.x);
  }
  
  /* Get the values of the two subtrees. */
  Integer left = getValue(new Point(p.x, p.y + 1));
  Integer right = getValue(new Point(p.x + 1, p.y + 1));
  Integer value = tree.get(p.y).get(p.x) + Math.max(left, right);
  
  values.put(p, value);
  return value;  
 }

 public static void main(String[] args) {
  /* TODO: read tree from file. */
  
  System.out.println(getValue(new Point(0,0)));
 }

}
&lt;/pre&gt;
&lt;br /&gt;
This solution is a sketch. I leave parsing the tree from a file as an exercise to the reader. Note that if you&#39;re serious about perfomance, using Integer and other boxed types is a bad idea. I would strongly recommend using the &lt;a href=&quot;http://trove.starlight-systems.com/&quot;&gt;Trove High Performance Collections&lt;/a&gt; for the cache.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;Until next time!</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/8774240522428430510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/10/skills-every-programmer-should-have-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/8774240522428430510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/8774240522428430510'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/10/skills-every-programmer-should-have-1.html' title='Skills every programmer should have #1: Dynamic programming'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-4250327862433608435</id><published>2011-08-27T05:51:00.000-07:00</published><updated>2012-12-23T03:12:37.296-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="listview"/><title type='text'>Lazy loading of images in Listview</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicQRgUwGiUSRe-Ckw94Yha08wRSTmp6gDC9m8V_j8ULVCEFbODZkgJPdDRyfuhqP8MYYo561I07ttodCza07lpqrtY9vFuw3h9ibvjK36WNd4nqyXQYo29iqwhycajlJvuHLukyMseJbLV/s1600/android-accounts-sync.jpg&quot; imageanchor=&quot;1&quot; style=&quot;clear:left; float:left;margin-right:1em; margin-bottom:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; width=&quot;289&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicQRgUwGiUSRe-Ckw94Yha08wRSTmp6gDC9m8V_j8ULVCEFbODZkgJPdDRyfuhqP8MYYo561I07ttodCza07lpqrtY9vFuw3h9ibvjK36WNd4nqyXQYo29iqwhycajlJvuHLukyMseJbLV/s320/android-accounts-sync.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

A common scenario is adding images to a Listview. For example, if you´re making a cocktail recipe app, you´d want a picture next to the cocktail name. Sometimes the images should be retrieved from the internet and then be displayed. Unfortunately, this is difficult to do right. If you´ve tried it, you´ve probably noticed performance hits, or some strange glitches. In this tutorial, I´ll show you how to download images and display them. We´ll also discuss some pitfalls, like recycling and concurrency.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Setting up the listview&lt;/b&gt;&lt;br /&gt;
I assume you already know how to define a row layout for a Listview and know about adapters. &lt;br /&gt;
&lt;br /&gt;
Below is an example of an adapter for an RSS reader. The text data is retrieved from an Article class, which contains the title of the Article, the author and the publication date. To make the tutorial more clear, I have an explicit list of URLs that will be used for the images of each entry.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class ListAdapter extends ArrayAdapter&amp;lt;Article&amp;gt; {
 private List&amp;lt;Article&amp;gt; articles;
 private Context context;
 private final LayoutInflater inflator;

 private static final String[] URLS = {
   &quot;http://lh5.ggpht.com/_mrb7w4gF8Ds/TCpetKSqM1I/AAAAAAAAD2c/Qef6Gsqf12Y/s144-c/_DSC4374%20copy.jpg&quot;,
   &quot;http://lh5.ggpht.com/_Z6tbBnE-swM/TB0CryLkiLI/AAAAAAAAVSo/n6B78hsDUz4/s144-c/_DSC3454.jpg&quot;,
   &quot;http://lh3.ggpht.com/_GEnSvSHk4iE/TDSfmyCfn0I/AAAAAAAAF8Y/cqmhEoxbwys/s144-c/_MG_3675.jpg&quot;,
   &quot;http://lh6.ggpht.com/_Nsxc889y6hY/TBp7jfx-cgI/AAAAAAAAHAg/Rr7jX44r2Gc/s144-c/IMGP9775a.jpg&quot;,
   &quot;http://lh3.ggpht.com/_lLj6go_T1CQ/TCD8PW09KBI/AAAAAAAAQdc/AqmOJ7eg5ig/s144-c/Juvenile%20Gannet%20despute.jpg&quot;,
   &quot;http://lh6.ggpht.com/_ZN5zQnkI67I/TCFFZaJHDnI/AAAAAAAABVk/YoUbDQHJRdo/s144-c/P9250508.JPG&quot;,
   &quot;http://lh4.ggpht.com/_XjNwVI0kmW8/TCOwNtzGheI/AAAAAAAAC84/SxFJhG7Scgo/s144-c/0014.jpg&quot;,
   &quot;http://lh6.ggpht.com/_lnDTHoDrJ_Y/TBvKsJ9qHtI/AAAAAAAAG6g/Zll2zGvrm9c/s144-c/000007.JPG&quot;,
   &quot;http://lh6.ggpht.com/_qvCl2efjxy0/TCIVI-TkuGI/AAAAAAAAOUY/vbk9MURsv48/s144-c/DSC_0844.JPG&quot;,
   &quot;http://lh4.ggpht.com/_4f1e_yo-zMQ/TCe5h9yN-TI/AAAAAAAAXqs/8X2fIjtKjmw/s144-c/IMG_1786.JPG&quot;,
   &quot;http://lh6.ggpht.com/_iFt5VZDjxkY/TB9rQyWnJ4I/AAAAAAAADpU/lP2iStizJz0/s144-c/DSCF1014.JPG&quot;,
   &quot;http://lh5.ggpht.com/_hepKlJWopDg/TB-_WXikaYI/AAAAAAAAElI/715k4NvBM4w/s144-c/IMG_0075.JPG&quot;,
   &quot;http://lh6.ggpht.com/_OfRSx6nn68g/TCzsQic_z3I/AAAAAAABOOI/5G4Kwzb2qhk/s144-c/EASTER%20ISLAND_Hanga%20Roa_31.5.08_46.JPG&quot;,
   &quot;http://lh6.ggpht.com/_ZGv_0FWPbTE/TB-_GLhqYBI/AAAAAAABVxs/cVEvQzt0ke4/s144-c/IMG_1288_hf.jpg&quot;,
   &quot;http://lh6.ggpht.com/_a29lGRJwo0E/TBqOK_tUKmI/AAAAAAAAVbw/UloKpjsKP3c/s144-c/31012332.jpg&quot;,
   &quot;http://lh3.ggpht.com/_55Lla4_ARA4/TB6xbyxxJ9I/AAAAAAABTWo/GKe24SwECns/s144-c/Bluebird%20049.JPG&quot;,
   &quot;http://lh3.ggpht.com/_iVnqmIBYi4Y/TCaOH6rRl1I/AAAAAAAA1qg/qeMerYQ6DYo/s144-c/Kwiat_100626_0016.jpg&quot;,
   &quot;http://lh6.ggpht.com/_QFsB_q7HFlo/TCItd_2oBkI/AAAAAAAAFsk/4lgJWweJ5N8/s144-c/3705226938_d6d66d6068_o.jpg&quot;,
   &quot;http://lh5.ggpht.com/_JTI0xxNrKFA/TBsKQ9uOGNI/AAAAAAAChQg/z8Exh32VVTA/s144-c/CRW_0015-composite.jpg&quot;,
   &quot;http://lh6.ggpht.com/_loGyjar4MMI/S-InVNkTR_I/AAAAAAAADJY/Fb5ifFNGD70/s144-c/Moving%20Rock.jpg&quot;,
   &quot;http://lh4.ggpht.com/_L7i4Tra_XRY/TBtxjScXLqI/AAAAAAAAE5o/ue15HuP8eWw/s144-c/opera%20house%20II.jpg&quot;,
   &quot;http://lh3.ggpht.com/_rfAz5DWHZYs/S9cstBTv1iI/AAAAAAAAeYA/EyZPUeLMQ98/s144-c/DSC_6425.jpg&quot;,
   &quot;http://lh6.ggpht.com/_iGI-XCxGLew/S-iYQWBEG-I/AAAAAAAACB8/JuFti4elptE/s144-c/norvig-polar-bear.jpg&quot;,
   &quot;http://lh3.ggpht.com/_M3slUPpIgmk/SlbnavqG1cI/AAAAAAAACvo/z6-CnXGma7E/s144-c/mf_003.jpg&quot;,
   &quot;http://lh4.ggpht.com/_loGyjar4MMI/S-InQvd_3hI/AAAAAAAADIw/dHvCFWfyHxQ/s144-c/Rainbokeh.jpg&quot;,
   &quot;http://lh4.ggpht.com/_yy6KdedPYp4/SB5rpK3Zv0I/AAAAAAAAOM8/mokl_yo2c9E/s144-c/Point%20Reyes%20road%20.jpg&quot;,
   &quot;http://lh5.ggpht.com/_6_dLVKawGJA/SMwq86HlAqI/AAAAAAAAG5U/q1gDNkmE5hI/s144-c/mobius-glow.jpg&quot;,
   &quot;http://lh3.ggpht.com/_QFsB_q7HFlo/TCItc19Jw3I/AAAAAAAAFs4/nPfiz5VGENk/s144-c/4551649039_852be0a952_o.jpg&quot;,
   &quot;http://lh6.ggpht.com/_TQY-Nm7P7Jc/TBpjA0ks2MI/AAAAAAAABcI/J6ViH98_poM/s144-c/IMG_6517.jpg&quot;,
   &quot;http://lh3.ggpht.com/_rfAz5DWHZYs/S9cLAeKuueI/AAAAAAAAeYU/E19G8DOlJRo/s144-c/DSC_4397_8_9_tonemapped2.jpg&quot;,
   &quot;http://lh4.ggpht.com/_TQY-Nm7P7Jc/TBpi6rKfFII/AAAAAAAABbg/79FOc0Dbq0c/s144-c/david_lee_sakura.jpg&quot;,
   &quot;http://lh3.ggpht.com/_TQY-Nm7P7Jc/TBpi8EJ4eDI/AAAAAAAABb0/AZ8Cw1GCaIs/s144-c/Hokkaido%20Swans.jpg&quot;,
   &quot;http://lh3.ggpht.com/_1aZMSFkxSJI/TCIjB6od89I/AAAAAAAACHM/CLWrkH0ziII/s144-c/079.jpg&quot;,
   &quot;http://lh5.ggpht.com/_loGyjar4MMI/S-InWuHkR9I/AAAAAAAADJE/wD-XdmF7yUQ/s144-c/Colorado%20River%20Sunset.jpg&quot;,
   &quot;http://lh3.ggpht.com/_0YSlK3HfZDQ/TCExCG1Zc3I/AAAAAAAAX1w/9oCH47V6uIQ/s144-c/3138923889_a7fa89cf94_o.jpg&quot;,
   &quot;http://lh6.ggpht.com/_K29ox9DWiaM/TAXe4Fi0xTI/AAAAAAAAVIY/zZA2Qqt2HG0/s144-c/IMG_7100.JPG&quot;,
   &quot;http://lh6.ggpht.com/_0YSlK3HfZDQ/TCEx16nJqpI/AAAAAAAAX1c/R5Vkzb8l7yo/s144-c/4235400281_34d87a1e0a_o.jpg&quot;,
   &quot;http://lh4.ggpht.com/_8zSk3OGcpP4/TBsOVXXnkTI/AAAAAAAAAEo/0AwEmuqvboo/s144-c/yosemite_forrest.jpg&quot;,
   &quot;http://lh4.ggpht.com/_6_dLVKawGJA/SLZToqXXVrI/AAAAAAAAG5k/7fPSz_ldN9w/s144-c/coastal-1.jpg&quot;,
   &quot;http://lh4.ggpht.com/_WW8gsdKXVXI/TBpVr9i6BxI/AAAAAAABhNg/KC8aAJ0wVyk/s144-c/IMG_6233_1_2-2.jpg&quot;,
   &quot;http://lh3.ggpht.com/_loGyjar4MMI/S-InS0tJJSI/AAAAAAAADHU/E8GQJ_qII58/s144-c/Windmills.jpg&quot;,
   &quot;http://lh4.ggpht.com/_loGyjar4MMI/S-InbXaME3I/AAAAAAAADHo/4gNYkbxemFM/s144-c/Frantic.jpg&quot;,
   &quot;http://lh5.ggpht.com/_loGyjar4MMI/S-InKAviXzI/AAAAAAAADHA/NkyP5Gge8eQ/s144-c/Rice%20Fields.jpg&quot;,
   &quot;http://lh3.ggpht.com/_loGyjar4MMI/S-InZA8YsZI/AAAAAAAADH8/csssVxalPcc/s144-c/Seahorse.jpg&quot;,
   &quot;http://lh3.ggpht.com/_syQa1hJRWGY/TBwkCHcq6aI/AAAAAAABBEg/R5KU1WWq59E/s144-c/Antelope.JPG&quot;,
   &quot;http://lh5.ggpht.com/_MoEPoevCLZc/S9fHzNgdKDI/AAAAAAAADwE/UAno6j5StAs/s144-c/c84_7083.jpg&quot;,
   &quot;http://lh4.ggpht.com/_DJGvVWd7IEc/TBpRsGjdAyI/AAAAAAAAFNw/rdvyRDgUD8A/s144-c/Free.jpg&quot;,
   &quot;http://lh6.ggpht.com/_iO97DXC99NY/TBwq3_kmp9I/AAAAAAABcz0/apq1ffo_MZo/s144-c/IMG_0682_cp.jpg&quot;,
   &quot;http://lh4.ggpht.com/_7V85eCJY_fg/TBpXudG4_PI/AAAAAAAAPEE/8cHJ7G84TkM/s144-c/20100530_120257_0273-Edit-2.jpg&quot; };

 private static class ViewHolder {
  public ImageView iconView;
  public TextView nameTextView;
  public TextView bottomText;
 }

 public ListAdapter(Context context, int textViewResourceId,
   List&amp;lt;Article&amp;gt; articles) {
  super(context, textViewResourceId, articles);
  this.articles = articles;
  this.context = context;
  inflator = (LayoutInflater) context
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

  BitmapManager.INSTANCE.setPlaceholder(BitmapFactory.decodeResource(
    context.getResources(), R.drawable.icon));
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  ViewHolder holder;

  if (convertView == null) {
   convertView = inflator.inflate(R.layout.article_row, null);

   TextView nameTextView = (TextView) convertView
     .findViewById(R.id.title);
   TextView bottomText = (TextView) convertView
     .findViewById(R.id.bottomtext);
   ImageView iconView = (ImageView) convertView
     .findViewById(R.id.article_icon);
   holder = new ViewHolder();
   holder.nameTextView = nameTextView;
   holder.bottomText = bottomText;
   holder.iconView = iconView;
   convertView.setTag(holder);
  } else {
   holder = (ViewHolder) convertView.getTag();
  }

  Article article = articles.get(position);
  holder.nameTextView.setText(article.getTitle());
  holder.bottomText.setText(article.getAuthor() + &quot; | &quot;
    + article.getPubDate());

  holder.iconView.setTag(URLS[position]);
  BitmapManager.INSTANCE.loadBitmap(URLS[position], holder.iconView, 32,
    32);

  return convertView;
 }
}

&lt;/pre&gt;&lt;br /&gt;
As you can see, I am recycling the view, because I only inflate from XML when convertView == null. I also store references to all the children views in a tag. Recycling and tagging greatly improves performance, as can be seen in this &lt;a href=&quot;http://www.youtube.com/watch?v=N6YdwzAvwOA&quot;&gt;Google Conference video&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Downloading the bitmaps&lt;/b&gt;&lt;br /&gt;
A naive way to download a bitmap is to just make a http connection in the getView and set the bitmap using &lt;i&gt;iconView.setImageBitmap()&lt;/i&gt;. This would cause severe lag, because the UI thread would have to wait until the image is downloaded. What we want is to download in a separate thread. We also want some kind of cache to store downloaded bitmaps. &lt;br /&gt;
&lt;br /&gt;
All this can be done in a singleton BitmapManager. Here is the download function:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;private Bitmap downloadBitmap(String url, int width, int height) {
  try {
   Bitmap bitmap = BitmapFactory.decodeStream((InputStream) new URL(
     url).getContent());
   bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
   cache.put(url, new SoftReference&amp;lt;Bitmap&amp;gt;(bitmap));
   return bitmap;
  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }

  return null;
 }
&lt;/pre&gt;I don&#39;t know if this is the optimal way to download a file, so if you know a better way, please leave a message. As you can see, the bitmap is stored in cache, which is defined as  &lt;i&gt;Map&amp;lt;String, SoftReference&amp;lt;Bitmap&amp;gt;&amp;gt; cache;&lt;/i&gt;. We are using a SoftReference, because we want the bitmap to be garbage collected if the VM is low on memory.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The recycle trap&lt;/b&gt;&lt;br /&gt;
As I&#39;ve mentioned before, the row view can be recycled. This means that, if you&#39;re scrolling, the view of a row that slides off the screen, can be used as the view of a row that comes into the screen. For example, row 1 disappears and row 3 appears during scrolling. When row 1 was on the screen, the download of the image started. Now imagine that the downloaded of the image of row 1 takes a very long time. When row 3 appears, the image of row 3 is put into the queue. It may happen that this download finishes before the one of row 1, which means that the picture of row 3 will be the one of row 1.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Row 1 visible: start download of image 1
Scrolling
Row 3 visible (recycled view of row 1): start download of image 3
Download of image 3 done: row 3 image set to image 3
Download of image 1 done: row 3 image set to image 1
&lt;/pre&gt;&lt;br /&gt;
In order to avoid these recycling issues, we have to store the URL that is lastly associated with the ImageView. If a download is completed, but is not associated with the view anymore (image 1, in the example above), the download is ignored. This is the association map: &lt;i&gt;Map&amp;lt;ImageView, String&amp;gt; imageViews = Collections.synchronizedMap(new WeakHashMap&amp;lt;ImageView, String&amp;gt;());&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Retrieving the bitmap&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt; public void loadBitmap(final String url, final ImageView imageView,
   final int width, final int height) {
  imageViews.put(imageView, url);
  Bitmap bitmap = getBitmapFromCache(url);

  // check in UI thread, so no concurrency issues
  if (bitmap != null) {
   Log.d(null, &quot;Item loaded from cache: &quot; + url);
   imageView.setImageBitmap(bitmap);
  } else {
   imageView.setImageBitmap(placeholder);
   queueJob(url, imageView, width, height);
  }
 }
&lt;/pre&gt;The first thing we do when we load the bitmap, is associating the URL with the ImageView. Then we see if the bitmap is in the cache. If so, we load it from cache, or else we queue the download.&lt;br /&gt;
It should be noted that the loadBitmap function is called in the UI thread, which means that we don&#39;t have to check if the imageView is recycled and we can call functions like setImageBitmap directly.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The working thread&lt;/b&gt;&lt;br /&gt;
All that&#39;s left now is to call the downloadBitmap function from a new thread. Most code I saw online just spawns a new thread, but that can become very inefficient. Imagine that the Listview contains 500 items: that would mean that 500 threads would be spawned! Instead, we use the &lt;a href=&quot;http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html&quot;&gt;ExecutorService&lt;/a&gt; class from the Java Concurrency framework. We create a fixed thread pool (&lt;a href=&quot;http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)&quot;&gt;newFixedThreadPool&lt;/a&gt;) with 5 items (this number is arbitrary, I haven&#39;t tested which amount is optimal), which means that there will be up to five images that are downloaded at the same time. All the other downloads are stored in an unbounded queue.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public void queueJob(final String url, final ImageView imageView,
   final int width, final int height) {
  /* Create handler in UI thread. */
  final Handler handler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
    String tag = imageViews.get(imageView);
    if (tag != null &amp;amp;&amp;amp; tag.equals(url)) {
     if (msg.obj != null) {
      imageView.setImageBitmap((Bitmap) msg.obj);
     } else {
      imageView.setImageBitmap(placeholder);
      Log.d(null, &quot;fail &quot; + url);
     }
    }
   }
  };

  pool.submit(new Runnable() {
   @Override
   public void run() {
    final Bitmap bmp = downloadBitmap(url, width, height);
    Message message = Message.obtain();
    message.obj = bmp;
    Log.d(null, &quot;Item downloaded: &quot; + url);

    handler.sendMessage(message);
   }
  });
 }
&lt;/pre&gt;This code adds a new Runnable to the queue, which downloads the bitmap. Then it sends a message to a handler. A handler is used because all interactions with the UI have to be done in the UI thread. This means that we cannot directly set the image bitmap. A handler should be created in the thread the message will be handled in, so that&#39;s why we have to move the code outside of the Runnable anonymous class.&lt;br /&gt;
&lt;br /&gt;
In handleMessage the bitmap is retrieved from msg.obj. The bitmap is only set if the current URL is the last one to be associated with the ImageView. If the download failed for some reason, a placeholder is used.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
And there you have it. We&#39;ve made a lazy loading bitmap manager that works with recycled listviews. Some things could be done to improve performance even more, for example cancelling downloads if the view is destroyed and preventing downloading the same file at the same time. Anyhow, if you found this tutorial helpful, please leave a message :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Full code&lt;/b&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public enum BitmapManager {
 INSTANCE;

 private final Map&amp;lt;String, SoftReference&amp;lt;Bitmap&amp;gt;&amp;gt; cache;
 private final ExecutorService pool;
 private Map&amp;lt;ImageView, String&amp;gt; imageViews = Collections
   .synchronizedMap(new WeakHashMap&amp;lt;ImageView, String&amp;gt;());
 private Bitmap placeholder;

 BitmapManager() {
  cache = new HashMap&amp;lt;String, SoftReference&amp;lt;Bitmap&amp;gt;&amp;gt;();
  pool = Executors.newFixedThreadPool(5);
 }

 public void setPlaceholder(Bitmap bmp) {
  placeholder = bmp;
 }

 public Bitmap getBitmapFromCache(String url) {
  if (cache.containsKey(url)) {
   return cache.get(url).get();
  }

  return null;
 }

 public void queueJob(final String url, final ImageView imageView,
   final int width, final int height) {
  /* Create handler in UI thread. */
  final Handler handler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
    String tag = imageViews.get(imageView);
    if (tag != null &amp;amp;&amp;amp; tag.equals(url)) {
     if (msg.obj != null) {
      imageView.setImageBitmap((Bitmap) msg.obj);
     } else {
      imageView.setImageBitmap(placeholder);
      Log.d(null, &quot;fail &quot; + url);
     }
    }
   }
  };

  pool.submit(new Runnable() {
   @Override
   public void run() {
    final Bitmap bmp = downloadBitmap(url, width, height);
    Message message = Message.obtain();
    message.obj = bmp;
    Log.d(null, &quot;Item downloaded: &quot; + url);

    handler.sendMessage(message);
   }
  });
 }

 public void loadBitmap(final String url, final ImageView imageView,
   final int width, final int height) {
  imageViews.put(imageView, url);
  Bitmap bitmap = getBitmapFromCache(url);

  // check in UI thread, so no concurrency issues
  if (bitmap != null) {
   Log.d(null, &quot;Item loaded from cache: &quot; + url);
   imageView.setImageBitmap(bitmap);
  } else {
   imageView.setImageBitmap(placeholder);
   queueJob(url, imageView, width, height);
  }
 }

 private Bitmap downloadBitmap(String url, int width, int height) {
  try {
   Bitmap bitmap = BitmapFactory.decodeStream((InputStream) new URL(
     url).getContent());
   bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
   cache.put(url, new SoftReference&amp;lt;Bitmap&amp;gt;(bitmap));
   return bitmap;
  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }

  return null;
 }
}

&lt;/pre&gt;&lt;br /&gt;
In case you&#39;re wondering, an enum is the preferred way to create a singleton class.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/4250327862433608435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/lazy-loading-of-images-in-listview.html#comment-form' title='53 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/4250327862433608435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/4250327862433608435'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/lazy-loading-of-images-in-listview.html' title='Lazy loading of images in Listview'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicQRgUwGiUSRe-Ckw94Yha08wRSTmp6gDC9m8V_j8ULVCEFbODZkgJPdDRyfuhqP8MYYo561I07ttodCza07lpqrtY9vFuw3h9ibvjK36WNd4nqyXQYo29iqwhycajlJvuHLukyMseJbLV/s72-c/android-accounts-sync.jpg" height="72" width="72"/><thr:total>53</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-8276371904198886205</id><published>2011-08-13T03:54:00.000-07:00</published><updated>2012-12-23T03:38:51.306-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="animations"/><category scheme="http://www.blogger.com/atom/ns#" term="cutscenes"/><title type='text'>A cutscene framework for Android - part 3</title><content type='html'>We&#39;ve reached the third and final part of the tutorial on how to make cutscenes. Now that we&#39;ve already defined Actors and Animations, we just have to define the Cutscene. The cutscene should consist of a list of actors, the current frame and the frame at which the cutscene ends. Animations don&#39;t have to be included explicitly, because they are part of the &lt;i&gt;Actor&lt;/i&gt; class.&lt;br /&gt;
&lt;br /&gt;
You may ask why we need to explicitly define an end frame. We could also look at the frame at which all the animations of each actor have finished. If we set that frame as the end frame, the cutscene is cut off immediately after the last transition. This leaves no time to actually see what&#39;s going on. That&#39;s why we use an end frame.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class Cutscene {
 private Set&amp;lt;Actor&amp;gt; actors;
 private int endFrame;
 private int currentFrame;
 
 public Cutscene(Context context, int cutsceneResource) {
  load(context, cutsceneResource);
  currentFrame = 0;
 }
 
 public boolean isActive() {
  return currentFrame &amp;lt;= endFrame;
 }
 
 public Set&amp;lt;Actor&amp;gt; getActors() {
  return actors;
 }
 
 public void update() {
  if (!isActive()) {
   return;
  }
  
  for (Actor actor : actors) {
   actor.update();
  }
  
  currentFrame++;
 }
 
 public void draw(Canvas canvas) {
  for (Actor actor : actors) {
   actor.draw(canvas);
  }
 }
} 
&lt;/pre&gt;&lt;br /&gt;
As you can see, the Cutscene class is pretty straightforward. Using the framework so far, we can construct a cutscene from source code, with relative ease. It would be even better if we could just read it in from an XML file. For example, look at the following structure:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;cutscenes&amp;gt;
 &amp;lt;cutscene end=&quot;140&quot;&amp;gt;
  &amp;lt;actor type=&quot;text&quot; name=&quot;Intro&quot; x=&quot;10.0&quot; y=&quot;40.0&quot;
   visible=&quot;true&quot; text=&quot;This is the starting text.&quot;&amp;gt;
   &amp;lt;animation type=&quot;text&quot; start=&quot;50&quot; text=&quot;@string/anim_text&quot; /&amp;gt;
  &amp;lt;/actor&amp;gt;
  &amp;lt;actor type=&quot;bitmap&quot; name=&quot;Player&quot; visible=&quot;true&quot; x=&quot;0.0&quot; y=&quot;50.0&quot; bitmap=&quot;@drawable/player&quot;&amp;gt;
            &amp;lt;animation type=&quot;translate&quot; start=&quot;4&quot; end=&quot;60&quot; from_x=&quot;0.0&quot; from_y=&quot;50.0&quot; to_x=&quot;100.0&quot; to_y=&quot;50.0&quot; /&amp;gt;
  &amp;lt;/actor&amp;gt;
 &amp;lt;/cutscene&amp;gt;
&amp;lt;/cutscenes&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
All the elements of a simple scene are there: there is a text actor that displays two lines of text and a player bitmap that is moved across the screen. I&#39;ve added two different ways to add text: you either hardcode it, or you give a reference to a string.&amp;nbsp;The latter is recommended to support internationalisation.&lt;br /&gt;
&lt;br /&gt;
I&#39;ve given each actor a name, so that you can easily add additional information from source code.&amp;nbsp;For example, in my project the player bitmap is a subrectangle of the resource &lt;i&gt;@drawable/player&lt;/i&gt;. When this cutscene is parsed, I look for the actor with the name &lt;i&gt;Player&lt;/i&gt;, and I substitute the bitmap. If you want to have a custom bitmap, you should use &lt;i&gt;bitmap=&quot;custom&quot; &lt;/i&gt;in the XML.&lt;br /&gt;
&lt;br /&gt;
Now we have to parse the file:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public void load(Context context, int id) {
    actors = new HashSet&amp;lt;Actor&amp;gt;();
    
    XmlResourceParser parser = context.getResources().getXml(id);
    try {
        int eventType = parser.getEventType();
        
        Actor currentActor = null;
        
        while (eventType != XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_TAG) {
                if (parser.getName().equals(&quot;cutscene&quot;)) {
                    endFrame = parser.getAttributeIntValue(null, &quot;end&quot;, 0);
                }
                
                if (parser.getName().equals(&quot;actor&quot;)) {
                    String type = parser.getAttributeValue(null, &quot;type&quot;);
                    String name = parser.getAttributeValue(null, &quot;name&quot;);
                    float x = parser.getAttributeFloatValue(null, &quot;x&quot;, 0);
                    float y = parser.getAttributeFloatValue(null, &quot;y&quot;, 0);
                    boolean visible = parser.getAttributeBooleanValue(null,
                    &quot;visible&quot;, false);
                    
                    /* Read type specifics. */
                    if (type.equals(&quot;text&quot;)) {
                        String text = parser
                        .getAttributeValue(null, &quot;text&quot;);
                        int res = parser.getAttributeResourceValue(null,
                        &quot;text&quot;, -1);
                        if (res != -1) {
                            text = context.getResources().getString(res);
                        }
                        
                        // TODO: do something for paint. */
                        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                        paint.setColor(Color.WHITE);
                        currentActor = new TextActor(name, text,
                        new Vector2f(x, y), paint);
                        currentActor.setVisible(visible);
                    }
                    
                    if (type.equals(&quot;bitmap&quot;)) {
                        Bitmap bitmap = null;
                        if (!parser.getAttributeValue(null, &quot;bitmap&quot;)
                        .equals(&quot;custom&quot;)) {
                            int bitmapID = parser
                            .getAttributeResourceValue(null,
                            &quot;bitmap&quot;, -1);
                            bitmap = BitmapFactory.decodeResource(
                            context.getResources(), bitmapID);
                        }
                        
                        currentActor = new BitmapActor(name, bitmap,
                        new Paint());
                        currentActor.setVisible(visible);
                        currentActor.getTransform().setTranslate(x, y);
                    }
                    
                    if (currentActor != null) {
                        actors.add(currentActor);
                    }
                }
                
                if (parser.getName().equals(&quot;animation&quot;)) {
                    String type = parser.getAttributeValue(null, &quot;type&quot;);
                    int start = parser.getAttributeIntValue(null, &quot;start&quot;,
                    0);
                    int end = parser.getAttributeIntValue(null, &quot;end&quot;,
                    start);
                    
                    if (type.equals(&quot;text&quot;)) {
                        String text = parser
                        .getAttributeValue(null, &quot;text&quot;);
                        currentActor.addAnimation(new TextAnimation(text,
                        start));
                    }
                    
                    if (type.equals(&quot;translate&quot;)) {
                        float from_x = parser.getAttributeFloatValue(null,
                        &quot;from_x&quot;, 0);
                        float from_y = parser.getAttributeFloatValue(null,
                        &quot;from_y&quot;, 0);
                        float to_x = parser.getAttributeFloatValue(null,
                        &quot;to_x&quot;, 0);
                        float to_y = parser.getAttributeFloatValue(null,
                        &quot;to_y&quot;, 0);
                        currentActor.addAnimation(new TranslationAnimation(
                        new Vector2f(from_x, from_y), new Vector2f(
                        to_x, to_y), start, end));
                    }
                }
            }
            
            eventType = parser.next();
        }
        } catch (XmlPullParserException e) {
        e.printStackTrace();
        } catch (IOException e) {
        e.printStackTrace();
    }
}
&lt;/pre&gt;&lt;br /&gt;
This function reads the XML and creates a cutscene. I have left some things out, like defining a &lt;a href=&quot;http://developer.android.com/reference/android/graphics/Paint.html&quot;&gt;Paint&lt;/a&gt;&amp;nbsp;in the XML, because I haven&#39;t implemented those myself. If you want to do such a thing, I would recommend creating another XML structure just for Paints. Then you can add a reference to the resource in the cutscene structure. As you can see, this framework is easily extendable.&lt;br /&gt;
&lt;br /&gt;
And there you have it. In this tutorial you&#39;ve seen how to build a framework for cutscenes. We&#39;ve started with simple building blocks like animations and actors and finally we&#39;ve seen how to put them together to make cutscenes and read these from XML files. I hope you liked it!&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/8276371904198886205/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/cutscene-framework-for-android-part-3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/8276371904198886205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/8276371904198886205'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/cutscene-framework-for-android-part-3.html' title='A cutscene framework for Android - part 3'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-1796124250460779195</id><published>2011-08-10T13:50:00.000-07:00</published><updated>2011-08-10T13:50:14.438-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="dictionaries"/><category scheme="http://www.blogger.com/atom/ns#" term="keyboard"/><category scheme="http://www.blogger.com/atom/ns#" term="modding"/><title type='text'>Adding dictionaries to Android keyboard</title><content type='html'>I recently installed CyanogenMod-7.1.0-RC1 for my Wildfire, and I noticed that some dictionaries are missing from the default Gingerbread keyboard. What this means is that although you can select for example Dutch as input language, there will be no word suggestions. In this post I&#39;ll show you how to add those missing dictionaries.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Acquiring dictionaries&lt;/b&gt;&lt;br /&gt;
The keyboard application is stored in the file &lt;i&gt;/system/app/LatinIME.apk&lt;/i&gt;. Online, you can find different LatinIME&#39;s that have more dictionaries. I have compiled a list of dictionaries available to two custom roms:&lt;br /&gt;
&lt;br /&gt;
CyanogenMod: da, de, en, es, fr, it, iw, ka, pt, ru, sv&lt;br /&gt;
GingerVillain: da, de, en, es, it, nb, nl, sv&lt;br /&gt;
&lt;br /&gt;
There are more custom roms available that may have different languages and you could also try official roms from HTC or any other company that publishes Android phones. When you&#39;ve found and downloaded a good rom, store the file system/app/LatinIME.apk found in the zip.&lt;br /&gt;
&lt;br /&gt;
Now there are two options. The first is replacing LatinIME.apk and the second is modifying the original to support extra dictionaries. In my case, the two keyboards I wanted are English and Dutch, so for me replacing the CyanogenMod&#39;s LatinIME.apk with the one from GingerVillain was good enough. You can see below how to copy the file.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Adding a dictionary&lt;/b&gt;&lt;br /&gt;
To add something to an apk, we first need to extract the apk. This is done using &lt;a href=&quot;http://code.google.com/p/android-apktool/&quot;&gt;apktool&lt;/a&gt;. Download and extract both apktool and the helper scripts (depending on your OS) to the same folder.&lt;br /&gt;
&lt;br /&gt;
Also make sure that you have adb, the android debugger and that you&#39;ve set your phone to USB debugging mode (look &lt;a href=&quot;http://www.technixupdate.com/turn-on-usb-debugging-mode-in-nexus-one-or-other-android-phone/&quot;&gt;here&lt;/a&gt; if you don&#39;t know how to do that). To get adb you need to install the SDK platform tools (see &lt;a href=&quot;http://www.addictivetips.com/mobile/what-is-adb-and-how-to-install-it-android/&quot;&gt;here&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
Put the LatinIME.apk with the dictionary you want in the folder where you&#39;ve stored apktool and rename it to LatinIME_new.apk. When you&#39;ve done that open a console (cmd.exe in Windows) and navigate to the folder where you&#39;ve stored apktool.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;adb pull /system/app/LatinIME.apk LatinIME_old.apk
apktool d LatinIME_old.apk old
apktool d LatinIME_new.apk new
&lt;/pre&gt;&lt;br /&gt;
Now that you&#39;ve done that, you have two new folder: old and new. The old one contains the contents of the original LatinIME.apk and the new folder contains the dictionary you want. Go to the new directory and find res/raw-YOURLANG, where YOURLANG is the two letter abbreviation of your language. Now copy this directory to res folder in the old directory.&lt;br /&gt;
&lt;br /&gt;
Now that you&#39;ve added the file to the extracted apk, it&#39;s time to repackage it.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;apktool b old LatinIME.apk
&lt;/pre&gt;&lt;br /&gt;
The newly generated LatinIME.apk contains your dictionary, along with all the old ones. Now we have to upload this file to your phone.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Updating the LatinIME.apk file&lt;/b&gt;&lt;br /&gt;
When you&#39;ve got the LatinIME.apk you want, we can overwrite the file in your /system/app directory on your phone. Unfortunately, the /system folder is mounted read-only, so we have to remount it first. For the following steps, we make use of the &lt;i&gt;adb&lt;/i&gt; again.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;adb pull /system/app/LatinIME.apk LatinIME_backup.apk
adb remount
adb push LatinIME.apk /system/app/LatinIME.apk
&lt;/pre&gt;The first line makes a backup. You can leave that out if you&#39;ve already done so.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
Now that you&#39;ve updated your LatinIME.apk, you&#39;ll need the reboot your phone. After that, you&#39;re all set to use your new, fancy dictionary!&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/1796124250460779195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/adding-dictionaries-to-android-keyboard.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/1796124250460779195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/1796124250460779195'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/adding-dictionaries-to-android-keyboard.html' title='Adding dictionaries to Android keyboard'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-3329883182093964992</id><published>2011-08-09T13:40:00.000-07:00</published><updated>2012-12-23T03:39:26.332-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="animations"/><category scheme="http://www.blogger.com/atom/ns#" term="cutscenes"/><title type='text'>A cutscene framework for Android - part 2</title><content type='html'>In the last tutorial we&#39;ve made a framework for basic animations, like translation and text changes. Now it&#39;s time to put them together to transform an actor.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The actor&lt;/b&gt;&lt;br /&gt;
An abstract actor is an object that has variables that can be transformed. In most cases, an actor can be drawn to the screen. For this tutorial, we&#39;ll assume that they all do. The actor class should at least contain a set of animations and a transformation matrix that defines how the model is drawn on the screen.&lt;br /&gt;
&lt;br /&gt;
The actor also contains the elements that will be transformed by the animations, and therefore it should also be an &lt;i&gt;AnimationChangedListener&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public abstract class Actor implements AnimationChangedListener {&lt;br/&gt; private final String name;&lt;br/&gt; private boolean visible;&lt;br/&gt; private Matrix transform;&lt;br/&gt; private Set&amp;lt;Animation&amp;gt; animations;&lt;br/&gt;&lt;br/&gt; public Actor(String name) {&lt;br/&gt;  this.name = name;&lt;br/&gt;  visible = false;&lt;br/&gt;  animations = new HashSet&amp;lt;Animation&amp;gt;();&lt;br/&gt;  transform = new Matrix();&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public String getName() {&lt;br/&gt;  return name;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public Matrix getTransform() {&lt;br/&gt;  return transform;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public boolean isVisible() {&lt;br/&gt;  return visible;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public void setVisible(boolean visible) {&lt;br/&gt;  this.visible = visible;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; /**&lt;br/&gt;  * Adds an animation and links the actor as a listener.&lt;br/&gt;  * &lt;br/&gt;  * @param animation&lt;br/&gt;  *            Animation&lt;br/&gt;  */&lt;br/&gt; public void addAnimation(Animation animation) {&lt;br/&gt;  animations.add(animation);&lt;br/&gt;  animation.addListener(this);&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public void update() {&lt;br/&gt;  for (Animation animation : animations) {&lt;br/&gt;   animation.doTimeStep();&lt;br/&gt;  }&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt; public boolean isIdle() {&lt;br/&gt;  for (Animation animation : animations) {&lt;br/&gt;   if (!animation.isDone()) {&lt;br/&gt;    return false;&lt;br/&gt;   }&lt;br/&gt;  }&lt;br/&gt;  &lt;br/&gt;  return true;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; @Override&lt;br/&gt; public void valueChanged(Animation animation) {&lt;br/&gt;  float[] old = new float[9];&lt;br/&gt;  transform.getValues(old);&lt;br/&gt;&lt;br/&gt;  switch (animation.getType()) {&lt;br/&gt;  case POSITION:&lt;br/&gt;   Vector2f trans = (Vector2f) animation.getCurrentValue();&lt;br/&gt;   Vector2f diff = trans.sub(new Vector2f(old[Matrix.MTRANS_X],&lt;br/&gt;     old[Matrix.MTRANS_Y]));&lt;br/&gt;   transform.postTranslate(diff.getX(), diff.getY());&lt;br/&gt;   break;&lt;br/&gt;  case VISIBILITY:&lt;br/&gt;   visible = (Boolean) animation.getCurrentValue();&lt;br/&gt;   break;&lt;br/&gt;  }&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public final Vector2f getPosition() {&lt;br/&gt;  float[] old = new float[9];&lt;br/&gt;  transform.getValues(old);&lt;br/&gt;  return new Vector2f(old[Matrix.MTRANS_X], old[Matrix.MTRANS_Y]);&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public abstract void draw(Canvas canvas);&lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;br /&gt;
The base class Actor listens to two animations: a visibility animation and a translation animation. The exact implementation of the visibility animation is something I leave up to the reader, but it&#39;s just a simple switch at a certain frame. At this time, I use the &lt;a href=&quot;http://developer.android.com/reference/android/graphics/Matrix.html&quot;&gt;Matrix class&lt;/a&gt; from Android to store the rotations, scaling and translations, but due to the lack of getters like getPosition or getRotation, I may replace this code with my own Matrix class. Alternatively, I could store the rotation, translation and scale in three different variables.&lt;br /&gt;
&lt;br /&gt;
I have given the actor a name, so it can be identified at a later point, for debugging or for setting specifics in the source code (instead of the XML, we&#39;ll get to that).&lt;br /&gt;
&lt;br /&gt;
The actor is abstract, because the &lt;i&gt;draw&lt;/i&gt; method is not implemented. We&#39;ll look at two very useful derived classes now.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The text actor&lt;/b&gt;&lt;br /&gt;
The text actor is an actor that displays a piece of text on the screen. We&#39;ll use the &lt;a href=&quot;http://developer.android.com/reference/android/graphics/Canvas.html#drawText(java.lang.String, float, float, android.graphics.Paint)&quot;&gt;drawText&lt;/a&gt; function of the Canvas for that. The class should also be an &lt;i&gt;AnimationChangedListener&lt;/i&gt;, because it has to receive a notification when a &lt;i&gt;TextAnimation&lt;/i&gt; changes the text.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class TextActor extends Actor implements AnimationChangedListener {&lt;br/&gt; private String text;&lt;br/&gt; private final Paint paint;&lt;br/&gt;&lt;br/&gt; public TextActor(String name, String text, Vector2f pos, Paint paint) {&lt;br/&gt;  super(name);&lt;br/&gt;  this.text = text;&lt;br/&gt;  this.paint = paint;&lt;br/&gt;&lt;br/&gt;  getTransform().setTranslate(pos.getX(), pos.getY());&lt;br/&gt; }&lt;br/&gt;  &lt;br/&gt; public Paint getPaint() {&lt;br/&gt;  return paint;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; @Override&lt;br/&gt; public void valueChanged(Animation animation) {&lt;br/&gt;  if (animation.getType() == AnimationType.TEXT) {&lt;br/&gt;   text = (String) animation.getCurrentValue();&lt;br/&gt;  }&lt;br/&gt;&lt;br/&gt;  super.valueChanged(animation);&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; @Override&lt;br/&gt; public void draw(Canvas canvas) {&lt;br/&gt;  Vector2f pos = getPosition();&lt;br/&gt;  canvas.drawText(text, pos.getX(), pos.getY(), paint);&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt;}
&lt;/pre&gt;&lt;br /&gt;
The class also requires a &lt;a href=&quot;http://developer.android.com/reference/android/graphics/Paint.html&quot;&gt;Paint&lt;/a&gt; instance to draw the text correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The bitmap actor&lt;/b&gt;&lt;br /&gt;
Probably the most important actor is the bitmap actor: this class draws a bitmap to the screen using a certain transformation (defined in the base class). The implementation is very simple:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;&lt;br/&gt;public class BitmapActor extends Actor {&lt;br/&gt; private Bitmap bitmap;&lt;br/&gt; private final Paint paint;&lt;br/&gt;&lt;br/&gt; public BitmapActor(String name, Bitmap bitmap, Paint paint) {&lt;br/&gt;  super(name);&lt;br/&gt;  this.bitmap = bitmap;&lt;br/&gt;  this.paint = paint;&lt;br/&gt;  setVisible(false);&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt; public void setBitmap(Bitmap bitmap) {&lt;br/&gt;  this.bitmap = bitmap;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; public void draw(Canvas canvas) {&lt;br/&gt;  if (bitmap != null &amp;amp;&amp;amp; isVisible()) {&lt;br/&gt;   canvas.drawBitmap(bitmap, getTransform(), paint);&lt;br/&gt;  }&lt;br/&gt; }&lt;br/&gt;}
&lt;/pre&gt;&lt;br /&gt;
Now that we&#39;ve seen how to make actors, what&#39;s left is to put them together in a cutscene. Additionally, we&#39;ll learn how to define these cutscenes in simple XML. See you next time!&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/3329883182093964992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/cutscene-framework-for-android-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/3329883182093964992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/3329883182093964992'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/cutscene-framework-for-android-part-2.html' title='A cutscene framework for Android - part 2'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1177691919768241768.post-7273719555713799437</id><published>2011-08-05T05:46:00.000-07:00</published><updated>2012-12-23T03:40:03.862-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="android"/><category scheme="http://www.blogger.com/atom/ns#" term="animations"/><category scheme="http://www.blogger.com/atom/ns#" term="cutscenes"/><title type='text'>A cutscene framework for Android - part 1</title><content type='html'>Not many Android games I have played have cutscenes or lots of animations. Perhaps because it is hard to make. A cutscene requires higher quality sprites or meshes which the developers may not have. Secondly, and more importantly, coding all the animations is tedious. However, cutscenes contribute to the immersion of the player, much more than a static wall of text! In this tutorial series I will show you how to create a framework to create animations for multiple objects with relative ease. Over the course of this tutorial we&#39;ll look at the building blocks for cutscenes, like animations, actors and finally we&#39;ll learn to use an XML-format to quickly describe them all.&lt;br /&gt;
&lt;br /&gt;
The code is not Android-specific and could be used for other platforms as well.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Defining what we want&lt;/b&gt;&lt;br /&gt;
Before we start coding, we have to get a better sense of what we want to achieve. For a cutscene we want a scene with multiple objects. These objects could be anything, like a bitmap (sprite) or a piece of text. We will call these objects &lt;b&gt;actors&lt;/b&gt;. Each actor can be modified while playing the cutscene by an &lt;b&gt;animation&lt;/b&gt;. This could be anything as well, for example: a translation, a rotation, a change of text or a visibility toggle. An animation basically mutates a property of the actor. In this part, we&#39;ll look at how to define these animations.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Gathering some tools&lt;/b&gt;&lt;br /&gt;
First we&#39;ll check if Android has some handy tools for us. It seems that from Android 3.0 on, the&amp;nbsp;&lt;a href=&quot;http://developer.android.com/guide/topics/graphics/animation.html&quot;&gt;Property Animation&lt;/a&gt;&amp;nbsp;is very useful and may do about the same as the framework we&#39;re going to build. However, Android 3.0 is too much of a restriction for me. I want my games to run on Android phones from 2.1 on. Their second library called&amp;nbsp;&lt;a href=&quot;http://developer.android.com/guide/topics/graphics/view-animation.html&quot;&gt;View animations&lt;/a&gt;&amp;nbsp;is only applicable to views, so that&#39;s not useful for sprites rendered in OpenGL or bitmap rendered on a canvas.&lt;br /&gt;
&lt;br /&gt;
So it seems we have to do some things ourselves. That&#39;s ok, it&#39;s not a lot of work. First we start with some tools, a class that describes a 2d vector with float values: Vector2f.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;import android.os.Parcel;
import android.os.Parcelable;

public class Vector2f implements Parcelable {
 private final float x, y;

 public Vector2f(float x, float y) {
  super();
  this.x = x;
  this.y = y;
 }

 public Vector2f(Vector2f vec) {
  super();
  this.x = vec.x;
  this.y = vec.y;
 }

 public Vector2f(Vector2d vec) {
  super();
  this.x = vec.getX();
  this.y = vec.getY();
 }

 public float getX() {
  return x;
 }

 public float getY() {
  return y;
 }

 public Vector2f add(Vector2f vec) {
  return new Vector2f(x + vec.x, y + vec.y);
 }

 public Vector2f sub(Vector2f vec) {
  return new Vector2f(x - vec.x, y - vec.y);
 }

 public Vector2f scale(float f) {
  return new Vector2f(x * f, y * f);
 }

 public float lengthSquared() {
  return x * x + y * y;
 }

 @Override
 public String toString() {
  return &quot;(&quot; + x + &quot;, &quot; + y + &quot;)&quot;;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + Float.floatToIntBits(x);
  result = prime * result + Float.floatToIntBits(y);
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Vector2f other = (Vector2f) obj;
  if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x))
   return false;
  if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y))
   return false;
  return true;
 }

 public Vector2f(Parcel in) {
  x = in.readInt();
  y = in.readInt();
 }

 @Override
 public int describeContents() {
  return 0;
 }

 public static final Parcelable.Creator&amp;lt;Vector2f&amp;gt; CREATOR = new Parcelable.Creator&amp;lt;Vector2f&amp;gt;() {
  @Override
  public Vector2f createFromParcel(Parcel in) {
   return new Vector2f(in);
  }

  @Override
  public Vector2f[] newArray(int size) {
   return new Vector2f[size];
  }
 };

 @Override
 public void writeToParcel(Parcel dest, int flags) {
  dest.writeFloat(x);
  dest.writeFloat(y);

 }

}&lt;/pre&gt;&lt;br /&gt;
This is a thread-safe 2d vector implementation that&#39;s parcelable (useful if you want to store a vector using &lt;a href=&quot;http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)&quot;&gt;onSaveInstanceState&lt;/a&gt;). You can also see that a class Vector2d is mentioned, which is the same class only with ints instead of floats. I use Vector2d for positions in a grid.&lt;br /&gt;
&lt;br /&gt;
Next in line is defining an Animation. This will be the abstract framework on top of which all the possible animations are built. It should certainly have the start frame, the end frame and the current frame. The framerate itself is determined by the main loop of the application (a nice tutorial can be found&amp;nbsp;&lt;a href=&quot;http://obviam.net/index.php/the-android-game-loop/&quot;&gt;here&lt;/a&gt;). The Animation classes will all transform a single variable (this can be expanded) between those two keyframes. To identify which type of variable is transformed, I use an Enum. You could also use &lt;i&gt;instanceof.&amp;nbsp;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public abstract class Animation {
 private final int startFrame;
 private final int endFrame;
 private int currentFrame;
 private AnimationType type;
 private List&amp;lt;AnimationChangedListener&amp;gt; listeners;

 public Animation(int startFrame, int endFrame, AnimationType type) {
  super();
  this.startFrame = startFrame;
  this.endFrame = endFrame;
  this.type = type;

  currentFrame = 0;
  listeners = new ArrayList&amp;lt;AnimationChangedListener&amp;gt;();
 }

 public AnimationType getType() {
  return type;
 }

 public boolean isActive() {
  return currentFrame &amp;gt;= startFrame &amp;amp;&amp;amp; currentFrame &amp;lt;= endFrame;
 }

 public void addListener(AnimationChangedListener listener) {
  listeners.add(listener);
 }

 protected void dispatchValueChangedEvent() {
  for (AnimationChangedListener listener : listeners) {
   listener.valueChanged(this);
  }
 }

 /**
  * Can be overridden. This function should be called at the end.
  */
 public void doTimeStep() {
  if (currentFrame &amp;lt;= endFrame) {
   currentFrame++;
  }
 }

 public abstract Object getCurrentValue();
}

&lt;/pre&gt;&lt;br /&gt;
As you can see, I use an observer pattern to notify all listeners that a variable has changed. Because the abstract base class cannot see when a variable is changed, it is up to the derived classes to call &lt;i&gt;dispatchValueChangedEvent()&lt;/i&gt;. &lt;i&gt;AnimationChangedListener&lt;/i&gt; is a simple interface:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public interface AnimationChangedListener {
 void valueChanged(Animation animation);
}
&lt;/pre&gt;&lt;br /&gt;
Each time a frame is being updated, &lt;i&gt;doTimeStep&lt;/i&gt; is called. Classes that extend &lt;i&gt;Animation&lt;/i&gt; should do their logic there. Let&#39;s write a simple animation to see how this works in practice.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The translation animation&lt;/b&gt;&lt;br /&gt;
Image we want to translate a sprite on the screen between frames 10 and 20. The starting position is (0,0) and the final position is (100,100). This means that the velocity has to be:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;dir = end.sub(start).scale(1.f / (float) (endFrame - startFrame));&lt;/pre&gt;This is simply the distance divided by the time in frames. What&#39;s left now is to add &lt;i&gt;dir&lt;/i&gt; to the variable that tracks the position if the current frame is between the start frame and end frame, or in other words: when the animation is active.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;public class TranslationAnimation extends Animation {
 private final Vector2f dir;
 private Vector2f current;

 public TranslationAnimation(Vector2f start, Vector2f end, int startFrame,
   int endFrame) {
  super(startFrame, endFrame, AnimationType.POSITION);

  current = start;
  dir = end.sub(start).scale(1.f / (float) (endFrame - startFrame));
 }

 @Override
 public void doTimeStep() {
  if (isActive()) {
   current = current.add(dir);
   dispatchValueChangedEvent();
  }

  super.doTimeStep();
 }

 @Override
 public Object getCurrentValue() {
  return current;
 }
}
&lt;/pre&gt;&lt;br /&gt;
And there we have it. The animated variable can be retrieved by calling &lt;i&gt;getCurrentValue()&lt;/i&gt;. As we can see, that function returns an &lt;i&gt;Object&lt;/i&gt; and not a Vector2f. By querying the type with &lt;i&gt;getType()&lt;/i&gt; we know that the variable is a Vector2f. &lt;br /&gt;
&lt;br /&gt;
Instead of polling getCurrentValue all the time, it&#39;s better to use the callback from &lt;i&gt;dispatchValueChangedEvent()&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;The text changer&lt;/b&gt;&lt;br /&gt;
A second example of a useful animation in cutscenes is one that changes text. This is easily built:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:java&quot;&gt;&lt;br/&gt;public class TextAnimation extends Animation {&lt;br/&gt; private String text;&lt;br/&gt; private String newText;&lt;br/&gt;&lt;br/&gt; public TextAnimation(String newText, int startFrame) {&lt;br/&gt;  super(startFrame, startFrame, AnimationType.TEXT);&lt;br/&gt;  this.newText = newText;&lt;br/&gt;  text = null;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; @Override&lt;br/&gt; public void doTimeStep() {&lt;br/&gt;  if (isActive()) {&lt;br/&gt;   text = newText;&lt;br/&gt;   dispatchValueChangedEvent();&lt;br/&gt;  }&lt;br/&gt;&lt;br/&gt;  super.doTimeStep();&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt; @Override&lt;br/&gt; public Object getCurrentValue() {&lt;br/&gt;  return text;&lt;br/&gt; }&lt;br/&gt;&lt;br/&gt;}
&lt;/pre&gt;&lt;br /&gt;
This class doesn&#39;t store the original text, because that would complicate the constructor. It&#39;s no problem, because the listeners are only called when a real value is set.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We&#39;ve reached the end of tutorial one. Part 2 will come soon!</content><link rel='replies' type='application/atom+xml' href='http://negativeprobability.blogspot.com/feeds/7273719555713799437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/cutscene-framework-for-android-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/7273719555713799437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1177691919768241768/posts/default/7273719555713799437'/><link rel='alternate' type='text/html' href='http://negativeprobability.blogspot.com/2011/08/cutscene-framework-for-android-part-1.html' title='A cutscene framework for Android - part 1'/><author><name>Ben</name><uri>http://www.blogger.com/profile/16266302090312287528</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>