<?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>Scurvy Jake&#039;s Pirate Blog &#187; Code</title>
	<atom:link href="http://bogomip.net/blog/category/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://bogomip.net/blog</link>
	<description>Rated arrrr for Piracy</description>
	<lastBuildDate>Tue, 22 May 2012 21:31:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Using the yaml-cpp Library</title>
		<link>http://bogomip.net/blog/2010/06/19/using-the-yaml-cpp-library/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-the-yaml-cpp-library</link>
		<comments>http://bogomip.net/blog/2010/06/19/using-the-yaml-cpp-library/#comments</comments>
		<pubDate>Sat, 19 Jun 2010 18:57:42 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[MUD Development]]></category>
		<category><![CDATA[MUD]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=4299</guid>
		<description><![CDATA[I've been using the yaml-cpp library for a while now, and I have to say that overall I'm greatly pleased by how well it works. As I was making some adjustments to my I/O last night I ran across a bit of documentation that I never noticed before. Of course, it could be newly added. [...]]]></description>
			<content:encoded><![CDATA[<p>I've been using the <a href="http://code.google.com/p/yaml-cpp/">yaml-cpp library</a> for a while now, and I have to say that overall I'm greatly pleased by how well it works.</p>
<p>As I was making some adjustments to my I/O last night I ran across a bit of documentation that I never noticed before. Of course, it could be newly added. Anyway, I've found the most convenient way to parse my documents (I have many thousands of them to read and write), is to access them by node-name. For example:</p>
<pre>node["location"]["name"] >> mObjectLocation.location;</pre>
<p>The information I read last night, however, may convince me to change this behavior.</p>
<p>Apparently, named-node access in <code>yaml-cpp</code> is <strong>order-n<sup>2</sup> complex</strong> over the entire document. Put simply, every time you access a node like this the library loops through all nodes looking for a match. Personally, I think a hashed table lookup would have been much faster, and perhaps they'll add that later. </p>
<p>Overall, I wouldn't normally worry about it because my documents tend to only have a few dozen nodes. But I do have 20,000 documents to parse. And to top that off, as they are used they become more complex. And as more items are added, the node size will grow geometrically. I can easily envision a future where a single document contains hundreds of nodes, and it's starting to scare me.</p>
<p>The solution? Well, I can honestly say I don't have a good one yet. I think perhaps if I enforce the order things are written, which already only happens in one way, I can then read in linearly instead of by node-name. The problem with that is if a file is edited by hand and the order is accidentally changed. So by renaming my <em>current</em> solution to <code>readCompatible()</code> and writing a new linear <code>read()</code> function, I should cut down on a lot of extra unnecessary processing.</p>
<p>But I'm still not sure that's the best solution. Any smart people out there have a better idea?</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2010/06/19/using-the-yaml-cpp-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Boost::Spirit 2 Redux</title>
		<link>http://bogomip.net/blog/2010/06/01/boostspirit-2-redux/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=boostspirit-2-redux</link>
		<comments>http://bogomip.net/blog/2010/06/01/boostspirit-2-redux/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 03:27:35 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[MUD Development]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[MUD]]></category>
		<category><![CDATA[spirit]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=4256</guid>
		<description><![CDATA[Well if you stopped by yesterday you may have read my post about Boost::Spirit 2 and the trouble I had converting to the new Spirit 2 library. Fortunately, Hartmut Kaiser, one of the Boost::Spirit authors must have a Google blog notification when Spirit is mentioned in a blog, because he left a comment with a [...]]]></description>
			<content:encoded><![CDATA[<p>Well if you stopped by yesterday you may have read my <a href="http://bogomip.net/blog/2010/05/31/boostspirit-2/">post about Boost::Spirit 2</a> and the trouble I had converting to the new Spirit 2 library. Fortunately, <a href="http://boost-spirit.com/home/">Hartmut Kaiser</a>, one of the <a href="http://boost.org/">Boost::Spirit</a> authors must have a Google blog notification when Spirit is mentioned in a blog, because he <strong>left a comment</strong> with a suggestion for me earlier!</p>
<p>Unfortunately, I still can't seem to get <code>qi::phrase_parse</code> to work right. The problem is that I'm trying to match one of a set of increasingly complicated grammar structures (perhaps starting at the most complicated and working backwards would fix this issue&#8230;). So, here is my problem in gruesome detail:</p>
<p>I'm implementing a <strong>get</strong> command for a MUD, an online text-only game system. Since I'm writing it from scratch, I decided to use some of the most up-to-date tools I could find to do so, and Boost has some terrific libraries that make this possible. As far as I can discern, the <strong>get</strong> command can come in the following forms:</p>
<ol>
<li>get hammer</li>
<li>get 20 nails</li>
<li>get hammer 2 <em>(the second hammer)</em></li>
<li>get 20 nails 3 <em>(20 of the 3rd type of nails visible)</em></li>
<li>get hammer from toolbelt</li>
<li>get 20 nails from bucket</li>
<li>get hammer from toolbox 2 <em>(the hammer from the second toolbox)</em></li>
<li>get 20 nails from bucket 3 <em>(you get the idea)</em></li>
<li>get hammer 3 from toolbox 2</li>
<li>get 20 nails 2 from bucket 3</li>
</ol>
<p>The problem comes when using <code>phrase_parse</code> with an empty space skip-parser. Given the two rules:</p>
<pre>bool res = qi::phrase_parse(first, str.end(),
				(
					+qi::alpha
				),
				' ',
				item
);</pre>
<p>And</p>
<pre>bool res = qi::phrase_parse(first, str.end(),
					(
						+qi::alpha
						>> "from"
						>> +qi::alpha
					),
					' ',
					item,
					container
);</pre>
<p>If I check the phrase <strong>get hammer from bucket</strong> it matches rule one, because after you remove all the spaces from the string it's just one long word! This is an unexpected result, and even if I check rule two before rule one I <em>only match rule one</em>!</p>
<p>And now I'm really lost. I imagine there's a better way to do this, but I can't seem to figure it out. Also, since my allergies are going crazy, I've got to take the night off anyway. Anybody out there know of a solution?</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2010/06/01/boostspirit-2-redux/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Boost::Spirit 2</title>
		<link>http://bogomip.net/blog/2010/05/31/boostspirit-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=boostspirit-2</link>
		<comments>http://bogomip.net/blog/2010/05/31/boostspirit-2/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 01:34:32 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[MUD Development]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[MUD]]></category>
		<category><![CDATA[spirit]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=4248</guid>
		<description><![CDATA[Last year I added Boost::Spirit to my MUD project. A few weeks ago I learned that all of the work I had done was deprecated in the new Spirit 2 library. I could still use "Spirit classic," but it is deprecated and may be removed at some point in the future. So I spent some [...]]]></description>
			<content:encoded><![CDATA[<p>Last year I added <a href="http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/index.html">Boost::Spirit</a> to my MUD project. A few weeks ago I learned that all of the work I had done was deprecated in the new Spirit 2 library. I could still use "Spirit classic," but it <em>is</em> deprecated and may be removed at some point in the future. So I spent some time today figuring out how to convert my grammar rules.</p>
<p>For example, in Spirit classic, I had this rule to handle the most complex rule for my <code>get</code> command. In this case, it handles a command like <em>get 20 items 2 from container 3</em>:</p>
<pre>rule6 = int_p[assign_a(mNumberToGet)] >> ' ' >>
			(+alpha_p)[assign_a(mItemToFind)] >> ' ' >>
			int_p[assign_a(mItemNumber)] >> ' ' >>
			str_p("from") >> ' ' >>
			(+alpha_p)[assign_a(mContainerToLookIn)] >> ' ' >>
			int_p[assign_a(mContainerNumber)];</pre>
<p>which could be tested by the following code: <code>if(parse(str.c_str(), rule6).full)</code></p>
<p>Here is the equivalent code in Spirit 2</p>
<pre>
	std::string::iterator first = str.begin();

	bool r = qi::parse(first, str.end(),
					(
						qi::int_ >> ' '
						>> +(~qi::char_(' ')) >> ' '
						>> qi::int_ 	>> ' '
						>> qi::lit("from") >> ' '
						>> +(~qi::char_(' ')) >> ' '
						>> qi::int_
					),
					mNumberToGet,
					mItemToFind,
					mItemNumber,
					mContainerToLookIn,
					mContainerNumber
	);

	if(r &#038;& first == command.end()) {
		return true;
	}</pre>
<p>In many ways, the new Spirit 2 library is better, and purports to be much faster as well. The <code>parse</code> function has certainly been made somewhat more convenient. Overall, I'd rather not have had to spend time on this, but the only other option is to lock in with an old version of <strong>Boost</strong> that may hamper me in the future.</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2010/05/31/boostspirit-2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Post Project Endorphins</title>
		<link>http://bogomip.net/blog/2010/04/06/post-project-endorphins/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=post-project-endorphins</link>
		<comments>http://bogomip.net/blog/2010/04/06/post-project-endorphins/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 21:53:36 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=4203</guid>
		<description><![CDATA[I'm just wrapping up a project I've had on my plate for months, and I'm feeling the happy brain feeling of finishing up something I've worried about for a long time. It wasn't terribly complicated, but was subject to constant interruption and upheaval while other projects came along. (FYI in case you don't know, my [...]]]></description>
			<content:encoded><![CDATA[<p>I'm just wrapping up a project I've had on my plate for months, and I'm feeling the <em>happy brain feeling</em> of finishing up something I've worried about for a long time.</p>
<p>It wasn't terribly complicated, but was subject to constant interruption and upheaval while other projects came along. (FYI in case you don't know, my work requires a great deal of multi-tasking).</p>
<p>My code is compiling fine now, and should be fairly complete. Some more walk-throughs today and testing tomorrow, and it'll be off my shoulders completely. Until testing finds a bug, anyway. And I'll finally be able to say "I've finished it" at my weekly status meeting.</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2010/04/06/post-project-endorphins/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New C++ MySQL Wrapper</title>
		<link>http://bogomip.net/blog/2009/08/28/new-c-mysql-wrapper/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=new-c-mysql-wrapper</link>
		<comments>http://bogomip.net/blog/2009/08/28/new-c-mysql-wrapper/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 23:53:36 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=3848</guid>
		<description><![CDATA[I've been writing a replacement C++ wrapper class using the MySQL API. The previous method worked, but was prone to memory overwrites. The syntax is much better now, too. Just include the two header files and: boost::shared_ptr&#60;MySQL_Server&#62; server = boost::shared_ptr&#60;MySQL_Server&#62;(new MySQL_Server("localhost", "user", "password", "database")); boost::shared_ptr&#60;Query&#62; = boost::shared_ptr&#60;Query&#62;(new Query(server)); query->setQuery("UPDATE table SET var=val"); if(query->execute()) { std::cout [...]]]></description>
			<content:encoded><![CDATA[<p>I've been writing a replacement C++ wrapper class using the MySQL API. The previous method worked, but was prone to memory overwrites. The syntax is much better now, too. Just include the two header files and:</p>
<pre>
boost::shared_ptr&lt;MySQL_Server&gt; server = boost::shared_ptr&lt;MySQL_Server&gt;(new MySQL_Server("localhost", "user", "password", "database"));

boost::shared_ptr&lt;Query&gt; = boost::shared_ptr&lt;Query&gt;(new Query(server));

query->setQuery("UPDATE table SET var=val");

if(query->execute()) {
  std::cout << query->getNumberOfAffectedRows();
} else {
  std::cout << query->getError();
}
</pre>
<p><code>SELECT</code> query results can be stepped through with the following:</p>
<pre>
for(unsigned int i=0; i &lt; query-&gt;getNumberOfResultRows(); ++i) {
  std::vector&lt;std::string&gt; row = query-&gt;getNextRow();
  ...
}
</pre>
<p>I think I'm going to like this new class a lot more than the old one!</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2009/08/28/new-c-mysql-wrapper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Code Question</title>
		<link>http://bogomip.net/blog/2009/07/09/code-question/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=code-question</link>
		<comments>http://bogomip.net/blog/2009/07/09/code-question/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 05:21:08 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[c++]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=3730</guid>
		<description><![CDATA[Anybody know why I can't do this? Given: class Room { typedef boost::shared_ptr&#60;Room&#62; RoomPointer; typedef std::map&#60;std::string, RoomPointer&#62; RoomList; ... } And in another object, reference it like this: RoomList mRoomList; if((Room::RoomList::iterator it = mRoomList.find("name")) != mRoomList.end()) { return it-&#62;second; } I always get error: â€˜::iteratorâ€™ has not been declared back from the compiler. If I [...]]]></description>
			<content:encoded><![CDATA[<p>Anybody know why I can't do this?</p>
<p>Given:</p>
<pre>
class Room {
  typedef boost::shared_ptr&lt;Room&gt; RoomPointer;
  typedef std::map&lt;std::string, RoomPointer&gt; RoomList;
 ...
}
</pre>
<p>And in another object, reference it like this:</p>
<pre>
RoomList mRoomList;
if((Room::RoomList::iterator it = mRoomList.find("name")) != mRoomList.end()) {
   return it-&gt;second;
}
</pre>
<p>I always get <strong>error: â€˜::iteratorâ€™ has not been declared</strong> back from the compiler.</p>
<p>If I do this, it works fine:</p>
<pre>
Room::RoomList::iterator it = mRoomList.find("name");
if(it != mRoomList.end()) {
   return it-&gt;second;
}
</pre>
<p>I ask because Nicolai Josuttis (in <em>The C++ Standard Library</em>) recommends comparing the iterator against the end() condition on the same line because of type conversion of various unsigned types that may be used.</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2009/07/09/code-question/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Boost::format</title>
		<link>http://bogomip.net/blog/2009/05/26/boostformat/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=boostformat</link>
		<comments>http://bogomip.net/blog/2009/05/26/boostformat/#comments</comments>
		<pubDate>Wed, 27 May 2009 00:09:19 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=3586</guid>
		<description><![CDATA[It's official, I really like boost::format! Forget all that old-school variable argument C-style code with the ellipsis(&#8230;), boost::format is where it's at!]]></description>
			<content:encoded><![CDATA[<p>It's official, I really like <a href="http://www.boost.org/doc/libs/1_39_0/libs/format/doc/format.html">boost::format</a>!</p>
<p>Forget all that old-school variable argument C-style code with the ellipsis(&#8230;), <em>boost::format</em> is where it's at!</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2009/05/26/boostformat/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Best Compiler Error EVER!</title>
		<link>http://bogomip.net/blog/2009/04/24/best-compiler-error-ever/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=best-compiler-error-ever</link>
		<comments>http://bogomip.net/blog/2009/04/24/best-compiler-error-ever/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 23:23:05 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=3436</guid>
		<description><![CDATA[I had this happen just a little while ago, and busted up laughing after I read it. I had to walk away from the computer! I thought it quite profound that the error about not finding the function prototype happened on line 404. FTW! Turns out I changed the header file but forgot to make [...]]]></description>
			<content:encoded><![CDATA[<p>I had this happen just a little while ago, and busted up laughing after I read it. I had to walk away from the computer!</p>
<p><img src="/images/404-prototype.png" alt="Error on line 404: function prototype not found" /></p>
<p>I thought it quite profound that the error about not finding the function prototype happened on line <strong>404</strong>.</p>
<p>FTW!</p>
<p>Turns out I changed the header file but forgot to make it an <code>unsigned int</code> in the cpp file.</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2009/04/24/best-compiler-error-ever/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qt and OpenGL</title>
		<link>http://bogomip.net/blog/2009/01/23/qt-and-opengl/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=qt-and-opengl</link>
		<comments>http://bogomip.net/blog/2009/01/23/qt-and-opengl/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 05:49:15 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=3169</guid>
		<description><![CDATA[About a year ago, I started poking around with OpenGL, and began to write a program to display majiang tiles. Well, with all the Qt I've been writing lately, I thought I'd move it into their API. I have to admit, Qt makes it easy to incorporate OpenGL into your program. Texture loading was really [...]]]></description>
			<content:encoded><![CDATA[<p>About a year ago, I started poking around with <a href="http://www.opengl.org/">OpenGL</a>, and began to write a program to display majiang tiles.</p>
<p>Well, with all the <a href="http://www.trolltech.com/">Qt</a> I've been writing lately, I thought I'd move it into their API. I have to admit, Qt makes it easy to incorporate OpenGL into your program. Texture loading was <em>really</em> easy, once I realized I forgot to add a call to <code>glEnable(GL_TEXTURE_2D);</code>.</p>
<p>Anyway, tonight I <a href="http://www.gimp.org/">gimp</a>ed up a quick image to map on to the cube. Here is the result:</p>
<p><img src="/images/majiang.png" alt="OpenGL majiang tile" /></p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2009/01/23/qt-and-opengl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trigonometry Lesson</title>
		<link>http://bogomip.net/blog/2009/01/21/trigonometry-lesson/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=trigonometry-lesson</link>
		<comments>http://bogomip.net/blog/2009/01/21/trigonometry-lesson/#comments</comments>
		<pubDate>Thu, 22 Jan 2009 01:44:08 +0000</pubDate>
		<dc:creator>Scurvy Jake</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://bogomip.net/blog/?p=3160</guid>
		<description><![CDATA[Today I went to one of our resident math geniuses for a trig lesson. Yes, trig&#8212;that thing you swore in high school was stupid and you'd never use it again. The problem was I'm drawing a pie chart and needed to find when the mouse was inside any one of the wedges. So here's how [...]]]></description>
			<content:encoded><![CDATA[<p>Today I went to one of our resident math geniuses for a trig lesson. Yes, trig&#8212;that thing you swore in high school was stupid and you'd never use it again.</p>
<p>The problem was I'm drawing a pie chart and needed to find when the mouse was inside any one of the wedges.<br />
<img src="/images/pie.png" alt="pie chart" /></p>
<p>So here's how you find whether a mouse click was inside a wedge of a pie chart:<br />
<img src="/images/trig.png" alt="pie wedge trigonometry" /><br />
Given that the circle is inscribed in a bounding box 200x200 pixels and a mouse click happened at (130,50), here's how you check it:</p>
<p>First, check the distance from the center of the circle to the click coordinates. If this distance is greater than the radius of the circle, you need not go any further. This part was easy and I remembered it from high school.</p>
<p>The center of the circle lies at (100, 100). The distance of the click at (130, 50) is:<br />
<code>sqrt((130-100)^2 + (50-100)^2)</code>, or the square root of the square of the difference between the x-coordinates plus the square of the difference between the y-coordinates. If this value is greater than 100 (the radius of our circle), the click is outside the circle and no more math is required.</p>
<p>Next comes the tricky part. If the click was inside the circle, you need to find the angle of the click. In the diagram, you should know angles <code>a, b, c, </code>and <code>d</code> because you already drew them. Depending on your API, you may have them in degrees, or sixteenths of degrees like I did.</p>
<p>So you start by normalizing the <code>x</code> and <code>y</code> coordinates. This means translate it to <code>(0, 0)</code>, or more simply <em>subtract the x and y value of the center from the x and y value of the click</em>. In my case this means my translated-x (<code>tx</code>) and translated-y (<code>ty</code>) are <strong>(30, -50)</strong> (130-100 and 50-100).</p>
<p>The tangent of the angle &theta; is the opposite over the adjacent side, which are your translated x and y coordinates. To find the angle you need to use <code>tan<sup>-1</sup> ty / tx</code>, or <code>atan(ty/tx)</code> if you include <em>cmath</em>. This result is in <strong>radians</strong>. Make sure <code>tx</code> is non-zero or you will have some problems here.</p>
<p>This part is important! If <code>tx</code> was negative, you must add &pi; to the radians to make sure you get the angle into the negative-x side of the graph! If you don't do this you'll have even more problems.</p>
<p>To convert &theta; to degrees, multiply the radians by <code>180 / &pi;</code>.</p>
<p>In my API (I'm using <a href="http://trolltech.com/">Qt</a>), the degrees go in the opposite direction, so I had to invert the angle.</p>
<p>Compare this result to angles <code>a-d</code> and you have your wedge!</p>
<img src="http://bogomip.net/blog/16cfc4b3/266bb3e7/CCBot/1.0 (+http://www.commoncrawl.org/bot.html).gif" />]]></content:encoded>
			<wfw:commentRss>http://bogomip.net/blog/2009/01/21/trigonometry-lesson/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

