<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Groby Unplugged &#187; Math</title>
	<atom:link href="http://www.robertblum.com/articles/category/math/feed" rel="self" type="application/rss+xml" />
	<link>http://www.robertblum.com</link>
	<description>Rachel Blum on Software, Games And The Rest Of Life</description>
	<lastBuildDate>Sat, 26 Dec 2009 20:26:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Lying with Graphs</title>
		<link>http://www.robertblum.com/articles/2008/05/24/lying-with-graphs</link>
		<comments>http://www.robertblum.com/articles/2008/05/24/lying-with-graphs#comments</comments>
		<pubDate>Sun, 25 May 2008 02:38:26 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/?p=166</guid>
		<description><![CDATA[Finally catching up on my RSS feeds, I ran across a post on Dare Obosanjo&#8217;s blog. He posted a comparison chart for the stock prices of Apple, Microsoft, and Google, under the catchy title &#8220;Race to the bottom&#8221;



This didn&#8217;t exactly jive with my recollection &#8211; I follow these stocks on a daily basis (and hold [...]]]></description>
			<content:encoded><![CDATA[<p>Finally catching up on my RSS feeds, I ran across a <a href="http://www.25hoursaday.com/weblog/2008/02/27/RaceToTheBottomPic.aspx">post on Dare Obosanjo&#8217;s blog</a>. He posted a comparison chart for the stock prices of Apple, Microsoft, and Google, under the catchy title &#8220;Race to the bottom&#8221;</p>

<p><img src="http://www.robertblum.com/wp-content/uploads/2008/05/be10a0b5-1747-45b1-830c-68abbc850d28.jpg" alt="BE10A0B5-1747-45B1-830C-68ABBC850D28.jpg" border="0" width="476" height="277" title="Dare's Race to the Bottom"/></p>

<p>This didn&#8217;t exactly jive with my recollection &#8211; I follow these stocks on a daily basis (and hold a bit of <a href="http://finance.google.com/finance?client=ob&amp;q=NASDAQ:AAPL">AAPL</a>), and that didn&#8217;t look <em>at all</em> like the image my mind had.</p>

<p>So I went to Yahoo and did a comparison chart over a slightly longer period (a year, instead of three months), and right up to the current point in time.</p>

<p><img src="http://www.robertblum.com/wp-content/uploads/2008/05/abf9f55e-ee17-4ae1-bef7-d4a9ea57a391.jpg" alt="ABF9F55E-EE17-4AE1-BEF7-D4A9EA57A391.jpg" border="0" width="476" height="277" title="one year, in comparison"/></p>

<p>And suddenly both Apple and Google outperform Microsoft quite handily. Now, to be clear, I&#8217;m not accusing Dare of trying to distort the truth &#8211; I&#8217;m using this as an example that shows how easily truth can be distorted by graphs. For all I know, Dare is simply posting a picture somebody else sent him, without checking the data &#8211; it&#8217;s tagged as <a href="http://www.25hoursaday.com/weblog/CategoryView,category,MindlessLinkPropagation.aspx">mindless link propagation</a>, after all.</p>

<p>Just goes to show &#8211; if you have to rely on data, better double check yourself.</p>

<p><em>Update: I&#8217;m guilty of the same thing myself &#8211; I didn&#8217;t notice Dare actually posted this back in February. Showed up in my new items, so I treated it as new. I guess it&#8217;s more mindless link propagation on my part&#8230;.</em></p>

<p>So here&#8217;s a one-year chart that also ends at the same time.</p>

<p><img src="http://www.robertblum.com/wp-content/uploads/2008/05/screensnapz.png" alt="ScreenSnapz.png" border="0" width="476" height="194" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2008/05/24/lying-with-graphs/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Beautiful Mathematical Sculptures</title>
		<link>http://www.robertblum.com/articles/2005/11/30/beautiful-mathematical-sculptures</link>
		<comments>http://www.robertblum.com/articles/2005/11/30/beautiful-mathematical-sculptures#comments</comments>
		<pubDate>Wed, 30 Nov 2005 14:56:31 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/11/30/beautiful-mathematical-sculptures</guid>
		<description><![CDATA[Stretching the boundaries of the &#8220;math&#8221; category, I&#8217;d like to point you to Bathsheba Grossman: an artist who makes stunning sculptures based on (amongst other things) mathematical operations.



The Vorocube &#8211; a tangible Voronoi network.

Should you find the time to browse her site, you&#8217;ll also find quite interesting 3D laser etchings in glass. And no, it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Stretching the boundaries of the &#8220;math&#8221; category, I&#8217;d like to point you to <a href="http://www.bathsheba.com/">Bathsheba Grossman</a>: an artist who makes stunning sculptures based on (amongst other things) mathematical operations.
</p>

<p><center><a href="http://www.bathsheba.com/sculpt/"><img src="http://www.robertblum.com/images/art/vorocube_front.jpg" width=325 height=354  border=0 alt="Vorocube" align=left/><br />
The Vorocube &#8211; a tangible Voronoi network.</a></center></p>

<p>Should you find the time to browse her site, you&#8217;ll also find quite interesting <a href="http://www.bathsheba.com/crystal/">3D laser etchings in glass</a>. And no, it&#8217;s not the tacky stuff you can buy at the mall &#8211; it&#8217;s really worth a look.</p>

<p>[Edit - fixed spelling]</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/11/30/beautiful-mathematical-sculptures/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Decomposing Matrices</title>
		<link>http://www.robertblum.com/articles/2005/02/14/decomposing-matrices</link>
		<comments>http://www.robertblum.com/articles/2005/02/14/decomposing-matrices#comments</comments>
		<pubDate>Mon, 14 Feb 2005 07:22:41 +0000</pubDate>
		<dc:creator>Robert Blum</dc:creator>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[Technote]]></category>

		<guid isPermaLink="false">http://www.robertblum.com/articles/2005/02/14/decomposing-matrices</guid>
		<description><![CDATA[[Edit 09/29/05 - explained how to extract negative scale]

[Edit 02/26/07 - fixed a math bug. Oops! Thanks, Karsten Isakovic!]

[Edit 06/24/09 - fixed another math bug. Oops! Thanks, Aaron!]
[Edit 06/24/09 - Added highlighting to matrix elements so you can see start/stop]

While this might almost sound like the title of a bad Zombie movie, it&#8217;s all about [...]]]></description>
			<content:encoded><![CDATA[<p>[Edit 09/29/05 - explained how to extract negative scale]</p>

<p>[Edit 02/26/07 - fixed a math bug. Oops! Thanks, Karsten Isakovic!]</p>

<p>[Edit 06/24/09 - fixed another math bug. Oops! Thanks, Aaron!]
[Edit 06/24/09 - Added highlighting to matrix elements so you can see start/stop]</p>

<p>While this might almost sound like the title of a bad Zombie movie, it&#8217;s all about taking matrices apart. While matrices are a great vehicle to handle transformations (in our case, in 3D graphics), they are a complete pain for humans to read. At least they are for me &#8211; whenever I debug 3D code and I look at a matrix, intense pain sets in. The set of values is essentially meaningless.</p>

<p>So what do we need to do? We need to split it apart, into its&#8217; basic components. These would usually be scale, rotation, and translation. Theoretically, there could be skew, but few 3D render engines use that.</p>

<p>If you&#8217;re working with a 3D library, you usually got a call that does exactly what I described above. In D3D, its D3DXMatrixDecompose (if your SDK is newer that Summer &#8216;04). But this call has a couple of drawbacks. First, it ties you to a specific sequence of rotations &#8211; Yaw,Pitch,Roll for D3D. If your rotations are applied in any other order, the values don&#8217;t mean much. And I prefer my rotations in XYZ order, so that&#8217;s not an option.</p>

<p>Even worse, though &#8211; most decomposers return you a quaternion. And while quaternions are really nifty beasts, they are even less readable than a matrix. Now, granted, you can then convert the quaternion into angles &#8211; but at this time, we&#8217;ve had a lot of pain already. So, let&#8217;s instead find out how to do that decomposition ourselves.</p>

<p>Theoretically, we could take the code for that decomposition from Shoemake, <em>Euler Angle Conversion</em>, in Graphics Gems IV. But first of all, that code is completely unreadable (and gives a great example why macros and short variable names are bad). And second, it doesn&#8217;t handle two exceptional cases that can occur when decompositing. So, let&#8217;s do it by hand.</p>

<p>Step one: Extract the translation. That&#8217;s trivial, really. Just pick the first three values in the last row (or column, if you&#8217;re doing column-major matrices)</p>

<p>Step two: The scale. That&#8217;s not much more difficult &#8211; take the 3&#215;3 submatrix that contains the scale, and compute the &#8220;length&#8221; of the three rows. Done. (Well, almost. This only accounts for positive scale &#8211; but negative scale is done quite easily, too. The determinant is your friend!)</p>

<p>[Edit - how exactly is the determinant your friend? ]</p>

<p>So how do we get if the scale is negative or positive? After all, the length computation always gives a positive. The answer is in the determinant of the matrix. I really can&#8217;t explain here how to compute it, or what it is, exactly &#8211; but head over to our friends at <a href="http://www.gamedev.net">gamedev.net</a> to get a <a href="http://www.gamedev.net/reference/programming/features/vecmatprimer/">decent primer on matrices</a>.</p>

<p>Anyways &#8211; we know that none, or up to three of our scales are negative. However, scaling negatively on two axes is the equivalent of rotating 180 degrees. (Insert pi/2 in the three basic transformation matrices, and you will see). That means I cannot detect if two scales are negative. Three negative scales is the same as a rotation by 180 degrees and one negative scale.</p>

<p>So all we can do is detect if we should have a negative scale or not. We can&#8217;t detect which axis &#8211; so we just need to pick one. And the sign to detect this is that the determinant of the normalized rotation matrix is less than 0.</p>

<p>If that&#8217;s the case, simply make one of the scales negative. I usually pick X &#8211; but really, it doesn&#8217;t matter. Mathematically, it&#8217;s all the same.</p>

<p>[End Edit]</p>

<p>Step three is where it&#8217;s getting interesting. We need to extract the rotation from that same 3&#215;3 submatrix, but the values seem gibberish at a first glance. So let&#8217;s see how we arrived at our rotation matrix. Here are the three basic rotation matrices:</p>

<p>X-Rotation:</p>

<table cellpadding="10">
<tbody>
<tr>
  <td bgcolor="#c0c0c0">1</td>
  <td bgcolor="#c0c0c0">0</td>
  <td bgcolor="#c0c0c0">0</td>
</tr>
<tr>
    <td bgcolor="#c0c0c0">0</td>
    <td bgcolor="#c0c0c0">Cos(x) </td>
    <td bgcolor="#c0c0c0">Sin(x) </td>
</tr>
<tr>
    <td bgcolor="#c0c0c0">0</td><td bgcolor="#c0c0c0">-Sin(x)</td><td bgcolor="#c0c0c0">Cos(x)</td></tr></tbody></table>

<p>Y-Rotation:</p>

<table cellpadding="10"><tbody>
<tr><td bgcolor="#c0c0c0">Cos(y) </td>
<td bgcolor="#c0c0c0">0 </td>
<td bgcolor="#c0c0c0">Sin(y)</td></tr>
<tr><td bgcolor="#c0c0c0">0</td><td bgcolor="#c0c0c0">1</td><td bgcolor="#c0c0c0">0</td></tr>
<tr><td bgcolor="#c0c0c0">Sin(y)</td><td bgcolor="#c0c0c0">0</td><td bgcolor="#c0c0c0">Cos(y)</td></tr></tbody>
</table>

<p>Z-Rotation:</p>

<table cellpadding="10"><tbody>
<tr><td bgcolor="#c0c0c0">Cos(z) </td>
<td bgcolor="#c0c0c0">Sin(z) </td><td bgcolor="#c0c0c0">0</td></tr>
<tr><td bgcolor="#c0c0c0">-Sin(z)</td><td bgcolor="#c0c0c0">Cos(z)</td><td bgcolor="#c0c0c0">0</td></tr>
<tr><td bgcolor="#c0c0c0">0</td><td bgcolor="#c0c0c0">0</td><td bgcolor="#c0c0c0">1</td></tr></tbody></table>

<p>We multiply them in the desired order (XYZ) and get:</p>

<table cellpadding="10"><tbody>
<tr>
<td bgcolor="#c0c0c0">Cos(y).Cos(z) </td>
<td bgcolor="#c0c0c0">Cos(y).Sin(z) </td>
<td bgcolor="#c0c0c0">-Sin(y)</td>
</tr>
<tr>
<td bgcolor="#c0c0c0">Cos(z).Sin(x).Sin(y) &#8211; Sin(z).Cos(x)</td>
<td bgcolor="#c0c0c0">Sin(x).Sin(y).Sin(z) + Cos(x).Cos(z)</td>
<td bgcolor="#c0c0c0">Sin(x).Cos(y)</td>
</tr>
<tr>
<td bgcolor="#c0c0c0">Cos(x).Cos(z).Sin(y) + Sin(x).Sin(z) </td>
<td bgcolor="#c0c0c0">Cos(x).Sin(y).Sin(z) &#8211; Sin(x).Cos(z) </td>
<td bgcolor="#c0c0c0">Cos(x).Cos(y)</td></tr></tbody></table>

<p>Slightly less mysterious than the data we see in our debugger, but the <a href="http://www.carinsurancerates.com/ask/claims/">question</a> remains: How do we get our angles from that? Let&#8217;s start easy &#8211; if you look at row 1, column 3, you&#8217;ll see that value is only dependent on a single angle &#8211; Y rotation.</p>

<p>So, easily enough, we get: 
<pre>
rotation.y=asin( - matrix._13 );
</pre></p>

<p>Leaves us with x and z. Staring a bit harder at the matrix, we find a nice pair of values in row 2&amp;3, column 3: Sin(x).Cos(y) and Cos(x).Cos(y). If we divide those two, we get Sin(x)/Cos(x) = Tan(x). So we just compute the arctangent of that value. Dividing those two values could of course get an overflow error, but nicely enough there&#8217;s a library function that takes care of that, atan2.</p>

<p>Now apply the same idea to row 1, column 1&amp;2, and you&#8217;ll get Tan(z), too. So, turning that into code, we get:
<pre>
rotation.x = atan2( matrix._23, matrix._33 );
rotation.z = atan2( matrix._12, matrix._11 );
</pre></p>

<p>But wait &#8211; we&#8217;re not quite done. We haven&#8217;t removed the scale from our matrix before doing this decompostion. We need to divide _11 by scale.x, and _33 by scale.z. Then again, any one of those two scales could be zero. So, no division here &#8211; we simply multiply the dividend with the scale instead. I.e.:</p>

<p><pre>
rotation.x = atan2( matrix._23<em>scale.x, matrix._33 );
rotation.z = atan2( matrix._12</em>scale.y, matrix._11 );
</pre></p>

<p>Are we there yet? Not quite! What if Cos(y) is zero? Then our above equations don&#8217;t work out &#8211; the division is undefined. Those are the two exceptions where the Gems IV code breaks down. Now, what we need to do in those cases is: We pin one of the two values arbitrarily to 0. (It doesn&#8217;t matter what value we pick there, but that makes our life easier. This is the mathematical equivalent of gimbal lock). Let&#8217;s set X-rotation to 0. We now know that Cos(x) = +1 and Sin(y) = +/-1. (And of course, Sin(x)=0,Cos(y)=0)</p>

<p>That lets us simplify the nasty equations in the matrix a bit. matrix._22 becomes Cos(z), and matrix._21 becomes -Sin(z). Which, again, gives us Tan(z), but without a division by zero.</p>

<p>All we need to do to detect this special case is see if Sin(y) is less than -0.999 or greater than 0.999 (or whatever margin of error we want to leave).</p>

<p>And finally, we have our rotation. Our matrix is readable by humans.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.robertblum.com/articles/2005/02/14/decomposing-matrices/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>
