<?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>Raymond Hill&#039;s blog</title>
	<atom:link href="http://www.raymondhill.net/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.raymondhill.net/blog</link>
	<description>...</description>
	<lastBuildDate>Sun, 29 Jan 2012 15:34:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>Afghanistan war death map vs. Wikileaks death map</title>
		<link>http://www.raymondhill.net/blog/?p=470</link>
		<comments>http://www.raymondhill.net/blog/?p=470#comments</comments>
		<pubDate>Fri, 24 Jun 2011 15:38:44 +0000</pubDate>
		<dc:creator>rhill</dc:creator>
				<category><![CDATA[Wikileaks]]></category>

		<guid isPermaLink="false">http://www.raymondhill.net/blog/?p=470</guid>
		<description><![CDATA[On June 23, 2011, The Guardian published an interactive map of Afghanistan peppered with dots, each of which represents a (war) incident in which at least one individual (civilian and/or combatant) died as a result. (The Guardian&#8216;s map is based on leaked materials which has been published by Wikileaks.) That got me thinking. Julian Assange/Wikileaks [...]]]></description>
			<content:encoded><![CDATA[<p>On June 23, 2011, <i>The Guardian</i> <a href="http://www.guardian.co.uk/news/datablog/interactive/2011/jun/23/afghanistan-deaths-mapped">published an interactive map of Afghanistan peppered with dots</a>, each of which represents a (war) incident in which at least one individual (civilian and/or combatant) died as a result. (The <i>Guardian</i>&#8216;s map is based on leaked materials which has been <a href="http://wikileaks.org/">published by Wikileaks</a>.)</p>
<p>That got me thinking. Julian Assange/Wikileaks has been branded as &#8220;dangerous&#8221;, &#8220;terroristic&#8221;, or merely presented as not-a-force-for-good by prominent politicans, pundits, including but not limited to:</p>
<ul>
<li><a href="http://www.news.com.au/breaking-news/police-feared-wikileaks-founder-julian-assanges-assassination/story-e6frfku0-1225974291912">United States vice-president Joe Biden</a> who described Assange as a &#8220;dangerous hi-tech terrorist&#8221;;
<li><a href="http://www.smh.com.au/technology/technology-news/fey-general-who-ignited-a-cyber-war-20101210-18sxk.html?skin=text-only">Sarah Palin</a> who thinks Assange should be &#8220;hunted down like Al Qaeda&#8221;, while <a href="http://english.aljazeera.net/news/europe/2010/12/2010123144744513729.html">other members of the Republican party</a> called for the capital sentence against Wikileaks personel;
<li><a href="http://calgary.openfile.ca/calgary/file/2011/04/follow-police-investigation-professors-comments">Canadian Thomas Flanagan who thinks Julian Assange should be assassinated</a> because &#8220;there is no good coming of [the publication of the leaked documents]&#8220;;
<li><a href="http://www.guardian.co.uk/commentisfree/cifamerica/2011/jan/03/zimbabwe-morgan-tsvangirai">James Richardson</a>, who stated that Wikileaks &#8220;ought to leave international relations to those who understand it – at least to those who understand the value of a life&#8221;;
<li><a href="http://www.miamiherald.com/2011/06/11/2260439/a-new-documentary-peers-into-the.html">Glenn Garvin</a> who stated that Assange has &#8220;difficulty translating binary code into flesh and blood&#8221;.
</ul>
<p>With the kind of statements as the ones listed above, I thought we should have as well a &#8220;Wikileaks death map&#8221;, such as the &#8220;Afghanistan war death map&#8221; published by the <i>Guardian</i>, but this one related to deadly incident as a result of Wikileaks&#8217; publication of leaked materials, and presented side-by-side with the &#8220;Afghanistan war death map&#8221;. So here it is:</p>
<p>Deadly incidents in Afghanistan resulting from the Afghanistan war (on principles of &#8220;war on terror&#8221;):<br />
<img src="http://www.cablegatesearch.net/images/afghanistan-death-map-war.png" alt="Afghanistan death map. Source: The Guardian (UK)" width="383" height="282" /><br />
<span style="font-size:smaller">(Image source: <a href="http://www.guardian.co.uk/news/datablog/interactive/2011/jun/23/afghanistan-deaths-mapped">The Guardian</a>: Data for December of 2006 through end of 2009)</span></p>
<p>Deadly incidents in Afghanistan resulting from the publication of leaked documents by Wikileaks (on principles of transparency/accountability):<br />
<img src="http://www.cablegatesearch.net/images/afghanistan-death-map-wikileaks.png" alt="Wikileaks death map." width="383" height="282" /><br />
<span style="font-size:smaller">(Data source: <a href="http://www.mcclatchydc.com/2010/11/28/104404/officials-may-be-overstating-the.html">here</a>, <a href="http://www.salon.com/news/opinion/glenn_greenwald/2010/12/01/wikileaks">here</a>, since Wikileaks first published in December of 2006.)</span></p>
<p>Here is the thing: This is about Afghanistan here, but the fact is that you could use the map of any country and be unable to place a single dot on the Wikileaks version of the map. (It would be nonsense to blame Wikileaks for the <a href="http://www.hawaiifreepress.com/main/ArticlesMain/tabid/56/articleType/ArticleView/articleId/502/Wikileaks-writers-killed-in-Kenya.aspx">assassination of two &#8220;Wikileaks-related senior human rights activists&#8221; in 2009 in Kenya</a>, possibly linked to their work investigating &#8220;extrajudicial assassinations by the Kenyan Police&#8221;, Wikileaks has actually been <a href="http://en.wikipedia.org/wiki/Information_published_by_WikiLeaks#Killings_by_the_Kenyan_police"><i>awarded</i></a> for redistributing the <a href="http://www.webcitation.org/5vKBp2oC5">report</a>.)</p>
<p>So, hum, next time someone is trying to convince you that Wikileaks is not a force for good, don&#8217;t let yourself all worked up by the rhetoric out there. Keep in mind principles of transparency and accountability are not readily embraced by those who thrive on secrecy, duplicity and unchecked powers, quite the opposite.</p>
<p>Note: Keep in mind the <i>Guardian</i>&#8216;s map is based on leaked materials published by Wikileaks, which covers Afghanistan between 2004-2009. <a href="http://tpmmuckraker.talkingpointsmemo.com/2010/04/gen_mcchrystal_weve_shot_an_amazing_number_of_peop.php">More</a> <a href="http://articles.latimes.com/2011/mar/03/world/la-fg-afghan-children-killed-20110303">deadly</a> <a href="http://articles.cnn.com/2010-08-21/world/afghanistan.civilians.killed_1_afghan-woman-civilian-deaths-coalition-forces?_s=PM:WORLD">incidents</a> <a href="http://news.antiwar.com/2011/04/12/nato-taliban-clash-kills-three-afghan-children/">beyond</a> <a href="http://uk.reuters.com/article/2011/06/24/uk-afghanistan-pakistan-shelling-idUKL3E7HO1TY20110624">2009</a> <a href="http://www.nytimes.com/2011/06/12/world/asia/12afghanistan.html">are</a> <a href="http://english.aljazeera.net/news/asia/2011/07/20117785226411750.html">not</a> <a href="http://english.aljazeera.net/indepth/opinion/2011/06/2011613931606455.html">included</a>, and neither are <a href="http://www.guardian.co.uk/world/2011/jul/15/cia-usa">casualities from</a> <a href="http://en.wikipedia.org/wiki/Casualties_of_the_Iraq_War">other</a> <a href="http://www.mcclatchydc.com/2011/08/31/122789/wikileaks-iraqi-children-in-us.html">U.S.-led wars</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.raymondhill.net/blog/?feed=rss2&#038;p=470</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Update to code to compute Voronoi diagrams</title>
		<link>http://www.raymondhill.net/blog/?p=458</link>
		<comments>http://www.raymondhill.net/blog/?p=458#comments</comments>
		<pubDate>Sun, 22 May 2011 13:26:25 +0000</pubDate>
		<dc:creator>rhill</dc:creator>
				<category><![CDATA[Computer graphics]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mathematics]]></category>

		<guid isPermaLink="false">http://www.raymondhill.net/blog/?p=458</guid>
		<description><![CDATA[On September 2010, I posted about my implementation of Fortune&#8217;s algorithm to compute Voronoi diagrams. There were some issues related to finite arithmetic precision, and I could see no way to fix this once and for all other then by using a binary tree structure rather than a plain array to hold the beachline. I [...]]]></description>
			<content:encoded><![CDATA[<p>On September 2010, I posted about <a href="http://www.raymondhill.net/blog/?p=9">my implementation of Fortune&#8217;s algorithm to compute Voronoi diagrams</a>. There were some issues related to finite arithmetic precision, and I could see no way to fix this once and for all other then by using a binary tree structure rather than a plain array to hold the beachline.</p>
<p>I finally got around to do it. I also took the opportunity to put <a href="https://github.com/gorhill/Javascript-Voronoi">the code on Github</a>, under a MIT license. Also, I modified the way Voronoi sites are passed to the <a href="http://www.raymondhill.net/voronoi/rhill-voronoi-core.js">Voronoi object</a>, to minimize the amount of data duplication.</p>
<p>Since this new version takes care of annoying arithmetic finite precision issues, this allowed me to finally implement an idea I had for another demo page for Voronoi diagrams &#8212; the precision issues were causing my original implementation to often fail, somehow using fractional counterparts for the Voronoi sites caused the algorithm to often break because of the finite precision.</p>
<p>So here is another page demonstrating how to use the Voronoi object: <b><a href="http://www.raymondhill.net/voronoi/rhill-voronoi-demo3.php">Fancy tiling</a></b>.</p>
<p>I found it works best with browsers having fast Javascript engine. I did not try it with Internet Explorer, I am curious to know how smooth the interface is with IE9 (which supports the canvas element natively), so if you do try it, please share here whether it&#8217;s fast enough for a fluid interface. Also, if you stumbled onto a pretty tiling of your own, share with all and paste the associated permalink here.</p>
<p>I plan to implement other modifications to my implementation of Fortune&#8217;s algorithm, particularly to get rid of choke points I have identified which should help improve performance significantly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.raymondhill.net/blog/?feed=rss2&#038;p=458</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>FineDiff, a character-level diff algorithm in PHP</title>
		<link>http://www.raymondhill.net/blog/?p=441</link>
		<comments>http://www.raymondhill.net/blog/?p=441#comments</comments>
		<pubDate>Tue, 22 Feb 2011 18:34:23 +0000</pubDate>
		<dc:creator>rhill</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[diff]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.raymondhill.net/blog/?p=441</guid>
		<description><![CDATA[[under construction] I needed a diff algorithm to efficiently generate compact string of opcodes of all the actions required to transform exactly the content of a &#8220;from&#8221; string into the content of a &#8220;to&#8221; string. So here is a demo page of the algorithm: FineDiff demo page And here is the PHP code on github: [...]]]></description>
			<content:encoded><![CDATA[<p>[under construction]</p>
<p>I needed a diff algorithm to efficiently generate compact string of opcodes of all the actions required to transform exactly the content of a &#8220;from&#8221; string into the content of a &#8220;to&#8221; string.</p>
<p>So here is a demo page of the algorithm:<br />
<a href="http://www.raymondhill.net/finediff/index.php">FineDiff demo page</a></p>
<p>And here is the PHP code on github:<br />
<a href="https://github.com/gorhill/PHP-FineDiff">PHP-FineDiff</a>.</p>
<p><code>finediff.php</code> contains the PHP <code>FineDiff</code> class, other files are for the web pages to demo the <code>FineDiff</code> class.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.raymondhill.net/blog/?feed=rss2&#038;p=441</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Javascript: Highlighting text across HTML tags</title>
		<link>http://www.raymondhill.net/blog/?p=272</link>
		<comments>http://www.raymondhill.net/blog/?p=272#comments</comments>
		<pubDate>Tue, 18 Jan 2011 18:56:15 +0000</pubDate>
		<dc:creator>rhill</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[highlight]]></category>

		<guid isPermaLink="false">http://www.raymondhill.net/blog/?p=272</guid>
		<description><![CDATA[I needed JavaScript code to highlight portions of text on a web page. At first I went with the quick and dirty, naive approach of using regular expressions to find a portion of text, and replacing it with the same portion of text, surrounded with &#60;span class="highlight"&#62;...&#60;/span&#62;. But that&#8217;s not a very good way to [...]]]></description>
			<content:encoded><![CDATA[<p>I needed JavaScript code to highlight portions of text on a web page. At first I went with the quick and dirty, naive approach of using regular expressions to find a portion of text, and replacing it with the same portion of text, surrounded with <code>&lt;span class="highlight"&gt;...&lt;/span&gt;</code>.</p>
<p>But that&#8217;s not a very good way to do this if the text is to contain HTML tags, as you could end up damaging the document structure by unexpectedly replacing HTML markups instead of just plain text.</p>
<p>So I took the time to rewrite the code to traverse the DOM, inspect each text node to find the portion of text to highlight, and replacing it with the same portion of text, surrounded with <code>&lt;span class="highlight"&gt;...&lt;/span&gt;</code>. This is a safe way to do this since text nodes do not contain HTML tags.</p>
<p>However, I wasn&#8217;t happy with the result, as there were cases where the portions of text to highlight were spanning two or more HTML tags, in which case, the text nodes found when walking the DOM tree do not match the whole portion of text I was trying to highlight.</p>
<p>To illustrate the problem, take the following dummy text:</p>
<blockquote><h2>The quick brown fox <a href="http://www.urbandictionary.com/define.php?term=jum">jum</a>ped</h2>
<p><em>over</em> the laz<u>y</u> dog.</p>
<p>The quick brown fox jumped <sup>over</sup> the lazy dog.</p>
<p>The quick brown fox jump<s>ed</s>s <s>over</s> the lazy dog.</p>
<p>The quick brown fox <span style="font-size:large">j</span><span style="font-size:x-large">u</span><span style="font-size:xx-large">m</span><span style="font-size:xx-large">p</span><span style="font-size:x-large">e</span><span style="font-size:large">d</span> over the lazy dog.</p>
<p>The quick brown fox <span style="font-size:22px"><span style="color:red">j</span><span style="color:green">u</span><span style="color:blue">m</span><span style="color:purple">p</span><span style="color:teal">e</span><span style="color:maroon">d</span></span> over the lazy dog.</p></blockquote>
<p>With this latest method, it isn&#8217;t possible to highlight all the instances of <strong>&#8220;jumped&#8221;</strong>, because in many instances, internally the text is not contiguous in a single DOM text node, as there are intervening HTML tags in the middle.</p>
<p>This is a caveat present in all the JavaScript &#8220;highlighter&#8221; algorithm I found, like <a href="http://www.nsftools.com/misc/SearchAndHighlight.htm">this one</a>, <a href="http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html">this one</a>, and also <a href="http://www.tedpavlic.com/post_simple_inpage_highlighting_example.php">this one</a>.</p>
<p>Asked to highlight &#8220;jumped&#8221;, the above code would result in:</p>
<blockquote><h2>The quick brown fox <a href="http://www.urbandictionary.com/define.php?term=jum">jum</a>ped</h2>
<p><em>over</em> the laz<u>y</u> dog.</p>
<p>The quick brown fox <span style="background-color:yellow">jumped</span> <sup>over</sup> the lazy dog.</p>
<p>The quick brown fox jump<s>ed</s>s <s>over</s> the lazy dog.</p>
<p>The quick brown fox <span style="font-size:large">j</span><span style="font-size:x-large">u</span><span style="font-size:xx-large">m</span><span style="font-size:xx-large">p</span><span style="font-size:x-large">e</span><span style="font-size:large">d</span> over the lazy dog.</p>
<p>The quick brown fox <span style="font-size:22px"><span style="color:red">j</span><span style="color:green">u</span><span style="color:blue">m</span><span style="color:purple">p</span><span style="color:teal">e</span><span style="color:maroon">d</span></span> over the lazy dog.</p></blockquote>
<p>Although these might be suitable for many applications, it wasn&#8217;t in my particular application.</p>
<p>So I decided to write a piece of JavaScript code which would take care of highlighting portions of text regardless of intervening HTML tags. I also wanted a self-sufficient (does not depend on any particular JavaScript framework), single function to make it easy for others to reuse the code.</p>
<p>So here it is:</p>
<p>Non-minified version: <a href="/dohighlight/dohighlight.js">dohighlight.js</a><br />
Minified version: <a href="/dohighlight/dohighlight-min.js">dohighlight-min.js</a></p>
<p>You are free yo use/modify the above code, as long as you preface the portion of code with, at the very least, a comment line which contains the URL to this blog entry. Preferably, I would appreciate that all the comment lines as seen in the above JavaScript files are kept along with the code.</p>
<h3>Syntax</h3>
<p><code>doHighlight(node, className, searchFor[, which]);</code></p>
<h3>Arguments</h3>
<ul>
<li><em>node</em> &#8211; (mixed) A reference to the DOM node, or a string representing the id of a DOM node which contains the text to highlight.
<li><em>className</em> &#8211; (string) The class name to assign to the portions of text to highlight.
<li><em>searchFor</em> &#8211; (mixed) A string, or a RegExp object, which will be used in searching for portions of text to highlight.
<li><em>which</em> &#8211; (integer, optional, default to 0) When <em>searchFor</em> is a RegExp, this specifies which subpattern to highlight.
</ul>
<h3>Notes</h3>
<ul>
<li>To keep the function as compact as possible, the arguments are not tested for validity. It is the programmer&#8217;s responsibility to feed the function with valid arguments.
</ul>
<h3>Example</h3>
<p>
<input id="textToHighlight" type="text" value="jumped"> <button id="highlightButton">Highlight</button> <button id="resetButton">Reset</button></p>
<blockquote id="test"><h2>The quick brown fox <a href="http://www.urbandictionary.com/define.php?term=jum">jum</a>ped</h2>
<p><em>over</em> the laz<u>y</u> dog.</p>
<p>The quick brown fox jumped <sup>over</sup> the lazy dog.</p>
<p>The quick brown fox jump<s>ed</s>s <s>over</s> the lazy dog.</p>
<p>The quick brown fox <span style="font-size:large">j</span><span style="font-size:x-large">u</span><span style="font-size:xx-large">m</span><span style="font-size:xx-large">p</span><span style="font-size:x-large">e</span><span style="font-size:large">d</span> over the lazy dog.</p>
<p>The quick brown fox <span style="font-size:22px"><span style="color:red">j</span><span style="color:green">u</span><span style="color:blue">m</span><span style="color:purple">p</span><span style="color:teal">e</span><span style="color:maroon">d</span></span> over the lazy dog.</p>
<ul>
<li>The quick brown fox
<li>jumped
<li>over
<li>the lazy dog.
</ul>
</blockquote>
<p>The JavaScript code for the above example:</p>
<pre>
(function(){
  var resetHighlight = function(){
    var elems = document.querySelectorAll('.highlight');
    var n = elems.length;
    while (n--){
      var e = elems[n];
      e.parentNode.replaceChild(e.childNodes[0], e);
      }
    };

  var e = document.querySelector('#highlightButton');
  if (!e) {return;}
  e.onclick = function(){
    resetHighlight();
<b>    var e = document.querySelector('#textToHighlight');</b>
    if (!e) {return;}
<b>    var searchFor = new RegExp(e.value.replace(/\s+/g,'\\s+'), 'gi');</b>
<b>    doHighlight('test', 'highlight', searchFor);</b>
    };

  e = document.querySelector('#resetButton');
  if (!e) {return;}
  e.onclick = resetHighlight;
})();
</pre>
<style>
.highlight {background-color:yellow;color:inherit;text-decoration:inherit}
</style>
<p><script type="text/javascript">
<!--
(function(){
  var resetHighlight = function(){
    var elems = document.querySelectorAll('.highlight');
    var n = elems.length;
    while (n--){
      var e = elems[n];
      e.parentNode.replaceChild(e.childNodes[0], e);
      }
    };
  var e = document.querySelector('#highlightButton');
  if (!e) {return;}
  e.onclick = function(){
    resetHighlight();
    var e = document.querySelector('#textToHighlight');
    if (!e) {return;}
    var searchFor = new RegExp(e.value.replace(/\s+/g,'\\s+'), 'gi');
    doHighlight('test', 'highlight', searchFor);
    };
  e = document.querySelector('#resetButton');
  if (!e) {return;}
  e.onclick = resetHighlight;
})();
// Author: Raymond Hill
// Version: 2011-01-17
// Title: HTML text hilighter
// Permalink: http://www.raymondhill.net/blog/?p=272
// Purpose: Hilight portions of text inside a specified element, according to a search expression.
// Key feature: Can safely hilight text across HTML tags.
// Notes: Minified using YUI Compressor (http://refresh-sf.com/yui/),
function doHighlight(A,c,z,s){var G=document;if(typeof A==="string"){A=G.getElementById(A)}if(typeof z==="string"){z=new RegExp(z,"ig")}s=s||0;var j=[],u=[],B=0,o=A.childNodes.length,v,w=0,l=[],k,d,h;for(;;){while(B<o){k=A.childNodes[B++];if(k.nodeType===3){j.push({i:w,n:k});v=k.nodeValue;u.push(v);w+=v.length}else{if(k.nodeType===1){if(k.tagName.search(/^(script|style)$/i)>=0){continue}if(k.tagName.search(/^(a|b|basefont|bdo|big|em|font|i|s|small|span|strike|strong|su[bp]|tt|u)$/i)<0){u.push(" ");w++}d=k.childNodes.length;if(d){l.push({n:A,l:o,i:B});A=k;o=d;B=0}}}}if(!l.length){break}h=l.pop();A=h.n;o=h.l;B=h.i}if(!j.length){return}u=u.join("");j.push({i:u.length});var p,r,E,y,D,g,F,f,b,m,e,a,t,q,C,n,x;for(;;){r=z.exec(u);if(!r||r.length<=s||!r[s].length){break}E=r.index;for(p=1;p<s;p++){E+=r[p].length}y=E+r[s].length;g=0;F=j.length;while(g<F){D=g+F>>1;if(E<j[D].i){F=D}else{if(E>=j[D+1].i){g=D+1}else{g=F=D}}}f=g;while(f<j.length){b=j[f];A=b.n;v=A.nodeValue;m=A.parentNode;e=A.nextSibling;t=E-b.i;q=Math.min(y,j[f+1].i)-b.i;C=null;if(t>0){C=v.substring(0,t)}n=v.substring(t,q);x=null;if(q<v.length){x=v.substr(q)}if(C){A.nodeValue=C}else{m.removeChild(A)}a=G.createElement("span");a.appendChild(G.createTextNode(n));a.className=c;m.insertBefore(a,e);if(x){a=G.createTextNode(x);m.insertBefore(a,e);j[f]={n:a,i:y}}f++;if(y<=j[f].i){break}}}}
// -->
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.raymondhill.net/blog/?feed=rss2&#038;p=272</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Cablegate cables: Full-text search</title>
		<link>http://www.raymondhill.net/blog/?p=258</link>
		<comments>http://www.raymondhill.net/blog/?p=258#comments</comments>
		<pubDate>Sun, 12 Dec 2010 18:41:48 +0000</pubDate>
		<dc:creator>rhill</dc:creator>
				<category><![CDATA[Wikileaks]]></category>

		<guid isPermaLink="false">http://www.raymondhill.net/blog/?p=258</guid>
		<description><![CDATA[Shortly after I decided to support Wikileaks by joining the mass-mirroring movement on Dec. 5th, I decided to work on a full-text search tool for the Cablegate&#8217;s cables. While I was working on it, I found out that such a tool &#8212; CableSearch &#8212; had already been released on Dec. 3rd by a group of [...]]]></description>
			<content:encoded><![CDATA[<p>Shortly after I decided to support Wikileaks by joining the <a href="http://wikileaks.raymondhill.net/Mirrors.html">mass-mirroring movement</a> on Dec. 5th, I decided to work on a full-text search tool for the Cablegate&#8217;s cables.</p>
<p>While I was working on it, I found out that such a tool &#8212; <a href="http://cablesearch.org/">CableSearch</a> &#8212; had already been released on Dec. 3rd by a group of reporters.</p>
<p>Oh well.</p>
<p>Anyways, I decided to keep going as I was almost finished, and on Dec. 9th, I worked my idea of a full-text search tool for the leaked cables publicly available on Wikileaks: <a style="font-weight:bold" href="http://www.cablegatesearch.net/search.php">cablegatesearch.net</a></p>
<p>Hope you find it useful.</p>
<p>I will continue to work on it, as I have a few more ideas which I think would improve browsing through the collection of leaked cables.</p>
<p><strong>Jan 1st, 2011 update:</strong> Found another full-text search tool for the cables, <a href="https://kabelsearch.org/">KABELS</a>. The more the merrier.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.raymondhill.net/blog/?feed=rss2&#038;p=258</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Canadian Thomas Flanagan: &#8220;Assange should be assassinated&#8221;</title>
		<link>http://www.raymondhill.net/blog/?p=209</link>
		<comments>http://www.raymondhill.net/blog/?p=209#comments</comments>
		<pubDate>Mon, 06 Dec 2010 21:19:21 +0000</pubDate>
		<dc:creator>rhill</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.raymondhill.net/blog/?p=209</guid>
		<description><![CDATA[Update, June 8, 2011: Investigation into prof&#8217;s call for Assange&#8217;s assassination dropped That would be Mr. Thomas Flanagan. Watch on Youtube Tom Flanagan: &#8220;Well, I think Assange should be assassinated, actually &#60;chuckles&#62;. I think Obama should put out a contract and maybe use a drone or something. &#8230; I would not feel unhappy if Assange [...]]]></description>
			<content:encoded><![CDATA[<p><i><b>Update, June 8, 2011:</b> <a href="http://calgary.openfile.ca/calgary/file/2011/04/follow-police-investigation-professors-comments#file-june11-people">Investigation into prof&#8217;s call for Assange&#8217;s assassination dropped</a></i></p>
<p style="text-align:center;font-size:small;font-family:sans-serif"><a href="http://www.youtube.com/watch?v=MjyKOGUGIt4"><img src="http://cablegate.raymondhill.net/flanagan-cbc.jpg" alt="Tom Flanagan"></a><br />That would be Mr. Thomas Flanagan. Watch on <a href="http://www.youtube.com/watch?v=MjyKOGUGIt4">Youtube</a></p>
<p><b>Tom Flanagan:</b> &ldquo;Well, I think <a href="http://en.wikipedia.org/wiki/Julian_Assange">Assange</a> should be assassinated, actually <i>&lt;chuckles&gt;</i>. I think Obama should put out a contract and maybe use a drone or something. &#8230; I would not feel unhappy if Assange &lsquo;disappeared&rsquo;.&rdquo;</p>
<p>Tom Flanagan is a <a href="http://poli.ucalgary.ca/profiles/thomas-flanagan">political science teacher at the University of Calgary</a>. He was formerly an adviser to current prime minister <a href="http://en.wikipedia.org/wiki/Stephen_Harper">Stephen Harper</a>.</p>
<p><b>Tom Flanagan:</b> &ldquo;I made a thoughtless comment that I have retracted with regret.&rdquo;</p>
<p>What&#8217;s not to regret when you stoop to the level of terrorists?</p>
<p>I suspect though that Mr. Flanagan was speaking his mind, the only thoughtless part was to speak up his mind loudly on national television. He better should have expressed his mind secretly to a U.S. embassy. Oh wait&#8230;</p>
<p>In opposition to, and protest against Canadian fellow-countryman Mr. Tom Flanagan:</p>
<p><a style="font-size:24px;font-weight:bold" href="http://wikileaks.raymondhill.net/index.html">Wikileaks mirror</a> (available since Dec. 5th), and a <a style="margin-top:0.25em;display:inline-block;font-size:20px;font-weight:bold" href="http://www.cablegatesearch.net/">Full-text search tool for the leaked cables</a> (available since Dec. 9th)</p>
<p>Raymond Hill<br />Canadian citizen</p>
<div style="border-top:1px solid #aaa">&nbsp;</div>
<p><b>Dec. 7, 2010:</b> <a href="http://www.theglobeandmail.com/news/politics/tom-flanagan-threatened-me-over-wikileaks-comment-toronto-woman-says/article1829169/">Tom Flanagan threatened me over WikiLeaks comment, Toronto woman says</a>, <i>Globe and Mail</i>. Tom Flanagan to a woman who complained to him via email re. his suggestion that of Assange should be assassinated: &ldquo;Better be careful, we know where you live.&rdquo; (Who is &ldquo;we&rdquo;?)</p>
<div style="border-top:1px solid #aaa">&nbsp;</div>
<p><b>Dec. 6, 2010:</b> <a href="http://www.vancouversun.com/news/Complaint+filed+over+call+assassinate+WikiLeaks+founder/3932805/story.html">Complaint filed over call to assassinate WikiLeaks founder</a>, <i>Vancouver Sun</i></p>
<div style="border-top:1px solid #aaa">&nbsp;</div>
<p><b>Dec. 6, 2010:</b> Just read <a href="http://www.guardian.co.uk/media/blog/2010/dec/06/julian-assange-wikileaks-latest">over at the <i>Guardian</i></a>: &ldquo;The US attorney general, speaking at a press conference in Washington, said: &lsquo;The lives of people who work for the American people have been put at risk. The American people themselves have been put at risk by these actions that I believe are arrogant, misguided and ultimately not helpful in any way.&rsquo; &rdquo;</p>
<p>You might want to read <a href="http://wlcentral.org/node/429">this piece here</a>, which makes a point that the U.S. government itself is much more a risk to the lives of people than Wikileaks is. The article conludes:</p>
<blockquote><p>Civilian Body Count so Far:</p>
<p><b>WikiLeaks:</b> approximately  0<br />
<b>America:</b> approximately 873,000</p></blockquote>
<p>Also, Assange didn&#8217;t call for the assassination of anybody, as opposed to, say, Canadian Tom Flanagan. But somehow we are suppose to believe he is a treat to the lives of people.</p>
<div style="border-top:1px solid #aaa">&nbsp;</div>
<ul>
<li>Dec. 7, 2010: <a href="http://www.abc.net.au/unleashed/41914.html">Open letter: To Julia Gillard, re Julian Assange</a>, <i>Australian Broadcast Corporation</i>. Excellent open letter, which goes on to mention some of the extremists calling for the assassination of Julian Assange. Tom Flanagan didn&#8217;t make it to the succinct list though.
<li>Dec. 6, 2010: <a href="http://www.guardian.co.uk/commentisfree/cifamerica/2010/dec/06/western-democracies-must-live-with-leaks">Live with the WikiLeakable world or shut down the net. It&#8217;s your choice</a>, <i>The Guardian</i>
<li>Dec. 6, 2010: <a href="http://www.salon.com/news/opinion/glenn_greenwald/2010/12/06/wikileaks/index.html">The lawless Wild West attacks WikiLeaks</a>, <i>Salon</i>
</ul>
<p><a href="https://www.eff.org/pages/say-no-to-online-censorship"><img src="https://w2.eff.org/images/no_censorship_button.jpg"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.raymondhill.net/blog/?feed=rss2&#038;p=209</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Javascript implementation of Fortune&#8217;s algorithm to compute Voronoi diagrams</title>
		<link>http://www.raymondhill.net/blog/?p=9</link>
		<comments>http://www.raymondhill.net/blog/?p=9#comments</comments>
		<pubDate>Mon, 27 Sep 2010 16:38:45 +0000</pubDate>
		<dc:creator>rhill</dc:creator>
				<category><![CDATA[Computer graphics]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Steven J. Fortune]]></category>
		<category><![CDATA[Voronoi]]></category>

		<guid isPermaLink="false">http://www.raymondhill.net/blog/?p=9</guid>
		<description><![CDATA[Here is my <a href="http://www.raymondhill.net/voronoi/rhill-voronoi-core.js">personal Javascript implementation</a> of Steven Fortune's algorithm to generate Voronoi diagrams. I started from scratch, and didn't use Fortune's suggested data structures (binary tree for the beachline, linked lists for the edges), this implementation relies only on Javascript arrays, but of course is based on the <strong>concepts</strong> underlying Steven Fortune's very clever algorithm (sweep line, beach line, circle events, etc.)]]></description>
			<content:encoded><![CDATA[<p><i><b>Update (2011-05-20):</b> The source code has been updated since this entry was posted. Refer now to <a href="https://github.com/gorhill/Javascript-Voronoi">Github</a> for the latest version of the Javascript code which implements Fortune&#8217;s algorithm to compute Voronoi diagrams.</i></p>
<p>In the summer of 2009, while looking for a generic way to create fancy tilings for <a href="http://www.raymondhill.net/puzzle-rhill/jigsawpuzzle-rhill.php">this project</a>, I became interested with <a href="http://en.wikipedia.org/wiki/Voronoi">Voronoi diagrams</a>, and realized this was the solution to my problem.</p>
<p>Eventually I understood that the most efficient way to compute Voronoi diagrams was to implement <a href="http://en.wikipedia.org/wiki/Fortune%27s_algorithm">Steven J. Fortune&#8217;s sweep line algorithm</a>. However, I couldn&#8217;t find any ready to use Javascript implementation of his algorithm at the time.</p>
<p>Looking around, I stumbled upon and decided to port a C# implementation by <a href="http://sites.google.com/site/bdittes/">Benjamin Dittes</a> I found <a href="http://www.codeproject.com/KB/recipes/fortunevoronoi.aspx">there</a>.</p>
<p>However, once the <a href="http://www.raymondhill.net/voronoi/old-voronoi.php">port was completed</a>, I realized there were unresolved issues with Benjamin Dittes&#8217; implementation, specifically, the computed Voronoi diagram was left unfinished, with dangling Voronoi edges and open Voronoi cells. At the time, I tried to add the missing code, to find out there was a deeper issue with the code, which issue prevented me from properly &ldquo;closing&rdquo; the Voronoi diagram. (Note: I believe the problem is in <a href="http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=11275&#038;zep=FortuneVoronoi%2fFortuneVoronoi.cs&#038;rzp=%2fKB%2frecipes%2ffortunevoronoi%2ffortunevoronoi.zip">VoronoiEdge.AddVertex() in FortuneVoronoi.cs</a>: the vertex should be added in an orderly manner.)</p>
<p>Before I could pinpoint the exact fix in the code, I moved on to other things, and left my Javascript port attempt of Benjamin&#8217;s code unattended since then.</p>
<p>A few weeks ago, I decided to get back at work to create a fully working Javascript implementation of Fortune&#8217;s algorithm to generate Voronoi diagram, but this time I started from scratch, with my own ideas on how to implement Fortune&#8217;s algorithm. [Note: Meanwhile, two more Javascript implementations to compute Voronoi diagrams have become available on the net: <a href="http://blog.thejit.org/2010/02/12/voronoi-tessellation/">Voronoi Tessellation</a> by Nicolas Garcia Belmonte, and <a href="http://code.google.com/p/javascript-voronoi/">A JavaScript implementation of the planar ordinary Voronoi diagram</a> by Greg Ross.]</p>
<p>So here is my <a href="http://www.raymondhill.net/voronoi/rhill-voronoi-core.js">personal Javascript implementation</a> of Steven Fortune&#8217;s algorithm to generate Voronoi diagrams. I didn&#8217;t use Fortune&#8217;s suggested data structures (binary tree for the &ldquo;beach line&rdquo;, linked lists for the edges), this implementation relies only on Javascript arrays, but of course is based on the <b>concepts</b> underlying Steven Fortune&#8217;s very clever algorithm (sweep line, beach line, circle events, etc.)</p>
<div id="voronoiControls"><button onclick="voronoiDemo.randomSites(parseInt(document.getElementById('voronoiNumberSites').value,10),true);voronoiDemo.render();">Create</button> or <button onclick="voronoiDemo.randomSites(parseInt(document.getElementById('voronoiNumberSites').value,10),false);voronoiDemo.render();">Add</button><br />
<input id="voronoiNumberSites" type="text" value="10" size="5" maxlength="5" /> sites randomly, or <button onclick="voronoiDemo.clearSites();voronoiDemo.render();">Clear all sites</button><span style="position:absolute;right:1em"><br />
<input type="checkbox" id="voronoiTrackMouse" value="0" /> <label for="male">Track mouse</label></span></div>
<div id="voronoiCanvasPlaceholder" style="border:1px solid gray;padding:4px;color:gray;">You should see a Voronoi diagram here if Javascript is enabled in your browser, and if your browser supports the HTML5 <code>&lt;canvas&gt;</code> tag.</div>
<p><span id="voronoiStats"></span></p>
<p><!--[if lt IE 9]>
<p style="color:red;font-size:85%;line-height:120%"><b>Note to users of Internet Explorer version 8 and lower:</b> I use <a href="http://code.google.com/p/explorercanvas/" href="http://code.google.com/p/explorercanvas/">excanvas.js</a> to simulate support of HTML5 <a href="http://en.wikipedia.org/wiki/Canvas_element" href="http://en.wikipedia.org/wiki/Canvas_element"><code>&lt;canvas&gt;</code></a> element. This is a neat Javascript library to allow generic support of HTML5 <code>&lt;canvas&gt;</code> through emulation, it appears to work just fine, but it is <b>very slow</b>, compared to those browsers which support <code>&lt;canvas&gt;</code> natively. Also, there seems to be issues with tracking the mouse inside the emulated <code>&lt;canvas&gt;</code> element. Best is to simply install a modern, compliant browser.</p>
<p><![endif]--></p>
<p>The center piece of Fortune&#8217;s algorithm is the “beach line,” i.e. the “curve formed by the lowest parabolic arcs,” as stated in this <a href="http://www.ams.org/samplings/feature-column/fcarc-voronoi">excellent tutorial of Fortune&#8217;s algorithm</a>. I myself refer to these “parabolic arcs” as “beach sections.” Each break in the beach line, that is, each transition between two distinct beach sections represents a Voronoi edge, shared by two Voronoi sites, and for which a start and end point must be found. A start and/or end point is defined for a Voronoi edge when a transition between two beach sections appears or disappears.</p>
<p>Steven J. Fortune suggested, and used a binary tree in his C implementation to represent the beach line. In Fortune&#8217;s binary tree, transitions between two beach sections are represented by “internal nodes” in his binary tree, beach sections themselves are represented by &#8220;leaf nodes.&#8221; The binary tree is theoretically the most efficient way to represent the beach line.</p>
<p>However, this implementation relies on a simple Javascript ordered array to maintain the beach line, and all items in the beach line array are beach section objects. I chose to use an ordered array over a binary tree to simplify this first implementation. In such an ordered array, the transitions between two beach sections are implicit, we do not need a dedicated data structure to represent them internally.</p>
<p>Using an ordered array, it is thus possible to use a <a href="http://en.wikipedia.org/wiki/Binary_search_algorithm">binary search</a>, so we still have the benefit of the binary tree, the ability of fast look-up of any particular beach section on the beach line.</p>
<p>There are two main disadvantages though of using an ordered array over a binary tree in Fortune&#8217;s algorithm:</p>
<ol>
<li>Modifying the beach line means removing/adding elements in the array, which means memory movements, which is more costly than adding/removing nodes in a binary tree. However, most certainly the memory moves are ultimately done using machine code (<a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice">Array.splice</a>), whereas the managing of a binary tree isn&#8217;t done natively in Javascript [This is no longer true for Javascript engines supporting <a href="http://en.wikipedia.org/wiki/Just-in-time_compilation">just-in-time compilation</a>, so I might move to a binary tree structure in a near future...]
</li>
<li>The other disadvantage, more serious, is the inability for Fortune&#8217;s circle events to keep a direct reference to their associated beach section, as is possible using a binary tree. Because of this, an extra look-up is required when a Fortune&#8217;s circle event needs to be processed, to find the associated beach section on the beach line. This is mitigated by the fact that a binary search is used to perform the look-up.</li>
</ol>
<p>Given the disadvantages detailed above, it is useful to note that in typical circumstances, the number of beach sections in the array describing the beach line is relatively low. As an example, for 1,000 randomly generated Voronoi sites, I gathered that the beach line grows to an average of 75 beach sections at any time. The fact that the number of beach sections on the beach line is relatively low helps both the performance of the binary search look-ups (log<sub>2</sub>(N) &minus; 1), and the memory movements due to insertion/removal of beach sections in the array.</p>
<p>On my Core i5-660 computer, running <a href="http://www.ubuntu.com/">Ubuntu Lucid Lynx</a>, rough measurements (using <a href="http://www.raymondhill.net/voronoi/rhill-voronoi-demo1.php">Demo 1</a>) showed that to compute a Voronoi diagram for 5,000 sites (rendering <em>not</em> included) required:</p>
<p><strong>Chromium v6.*:</strong> 150-180 ms (impressive!)<br />
<strong>Firefox 3.6.*:</strong> 1,500-1,600 ms<br />
<strong>IE 8 within Virtualbox:</strong> 6,000-10,000 ms<br />
<strong>Safari v5.* within Virtualbox:</strong> 500-1,000 ms<br />
<strong>Google Chrome v6.* within Virtualbox:</strong> 350-450 ms</p>
<p><a href="http://www.raymondhill.net/voronoi/rhill-voronoi.php">This page</a> uses an extended version of the <a href="http://www.raymondhill.net/voronoi/rhill-voronoi-core.js">core version</a> of the algorithm &#8212; less suitable for code reuse &#8212; allowing full control of the execution of the Fortune&#8217;s events queue, allowing examination of the beach line, and also useful as a tutorial for Fortune&#8217;s sweep line algorithm (it was also very useful as a debugging tool.)</p>
<p>The core version used on this blog post (<a href="http://www.raymondhill.net/voronoi/rhill-voronoi-core.js">rhill-voronoi-core.js</a>/<a href="http://www.raymondhill.net/voronoi/rhill-voronoi-core-min.js">rhill-voronoi-core-min.js</a>), is faster since it contains only the code to compute a Voronoi diagram, given a set of vertices. The rendering of the resulting Voronoi diagram is left to the user. A typical usage:</p>
<div style="margin-bottom:1em;overflow:auto;font-family:monospace;background-color:#ccc">
var vertices = [{x:300,y:300}, {x:100,y:100}, {x:200,y:500}, {x:250,y:450}];<br />
var bbox = {xl:0, xr:800, yt:0, yb:600};<br />
var voronoi = new Voronoi();<br />
voronoi.setSites(vertices);<br />
var result = voronoi.compute(bbox);<br />
<span class="code-comment">// render, further analyze, etc.</span><br />
<span class="code-comment">// . . .</span><br />
<span class="code-comment">// modify one site and re-compute</span><br />
var sites = voronoi.getSites();<br />
sites[0].x = 310;<br />
sites[0].y = 290;<br />
result = voronoi.compute(bbox);<br />
<span class="code-comment">// render, further analyze, etc.</span>
</div>
<p>You are free to use or modify all or portion of <a type="text/plain" href="http://www.raymondhill.net/voronoi/rhill-voronoi-core.js">rhill-voronoi-core.js</a> or <a type="text/plain" href="http://www.raymondhill.net/voronoi/rhill-voronoi-core-min.js">rhill-voronoi-core-min.js</a> under the <strike><a href="http://www.gnu.org/licenses/gpl.html">GNU General Public License</a></strike> <a href="https://en.wikipedia.org/wiki/MIT_License">MIT License</a>.</p>
<h3>Other interesting online Voronoi-related web pages:</h3>
<ul style="margin-top: 0.25em;">
<li><a href="http://ect.bell-labs.com/who/sjf/">Steven Fortune</a>&#8216;s web page — somewhere in there is his original algorithm in C language.</li>
<li><a href="http://www.skynet.ie/~sos/mapviewer/voronoi.php">Shane O&#8217;Sullivan</a>: A C++ port of Steven Fortune&#8217;s code. The site hosts a PDF document detailing Fortune&#8217;s algorithm: <a href="http://www.skynet.ie/~sos/mapviewer/docs/Voronoi_Diagram_Notes_1.pdf">Lecture 16: Voronoi Diagrams and Fortune’s Algorithm</a>.</li>
<li><a href="http://blog.thejit.org/2010/02/12/voronoi-tessellation/">Voronoi Tessellation</a> by Nicolas Garcia Belmonte — a faithful Javascript port of Steven Fortune&#8217;s C implementation.</li>
<li><a href="http://code.google.com/p/javascript-voronoi/">A JavaScript implementation of the planar ordinary Voronoi diagram</a> by Greg Ross — a non-Fortune algorithm allowing incremental computation of a Voronoi diagram.</li>
<li><a href="http://www.cs.hmc.edu/~mbrubeck/voronoi.html">Fortune&#8217;s Algorithm in C++</a> by Matt Brubeck, a C++ implementation.</li>
<li><a href="http://www.ams.org/samplings/feature-column/fcarc-voronoi">Voronoi Diagrams and a Day at the Beach</a> by David Austin, an excellent tutorial on Steven Fortune&#8217;s algorithm.</li>
<li><a href="http://www.pi6.fernuni-hagen.de/GeomLab/VoroGlide/">VoroGlide</a> (Java-based).</li>
</ul>
<p><!--[if lt IE 9]><br />
<script type="text/javascript" src="http://www.raymondhill.net/voronoi/excanvas.compiled.js"></script><br />
<![endif]--><br />
<script type="text/javascript" src="http://www.raymondhill.net/voronoi/rhill-voronoi-core-min.js"></script><br />
<script type="text/javascript">
<!--
var voronoiDemo = {
  voronoi: new Voronoi(),
  diagram: null,
  margin: 50,
  canvas: null,
  bbox: {xl:0,xr:600,yt:0,yb:500},
  init: function() {
    // create and insert canvas into page
    var el = document.getElementById('voronoiCanvasPlaceholder');
    this.canvas = document.createElement('canvas');
    this.canvas.setAttribute("width",el.offsetWidth);
    this.canvas.setAttribute("height","500");
    this.bbox.xr = el.offsetWidth;
    if (self.G_vmlCanvasManager) {
      this.canvas = self.G_vmlCanvasManager.initElement(this.canvas);
      }
    el.parentNode.replaceChild(this.canvas,el);
    // generate random sites and render resulting Voronoi
    this.randomSites(10,true);
    this.render();
    // add basic interactivity to entertain the reader
    this.canvas.onclick = function(e) {
      var mouse = voronoiDemo.normalizeEventCoords(e);
      voronoiDemo.addSite(mouse.x,mouse.y);
      voronoiDemo.diagram = voronoiDemo.voronoi.compute(voronoiDemo.bbox);
      voronoiDemo.render();
      };
    document.getElementById('voronoiTrackMouse').onclick = function() {
      if (this.checked) {
        voronoiDemo.canvas.onmousemove = function(e) {
          var sites = voronoiDemo.voronoi.getSites();
          if (!sites || !sites.length) {return;}
          var mouse = voronoiDemo.normalizeEventCoords(e);
          var site = sites[0];
          site.x = mouse.x;
          site.y = mouse.y;
          voronoiDemo.diagram = voronoiDemo.voronoi.compute(voronoiDemo.bbox);
          voronoiDemo.render();
          };
        }
      else {
        voronoiDemo.canvas.onmousemove = null;
        }
      voronoiDemo.render();
      };
    },
  clearSites: function() {
    // we want at least one site, the one tracking the mouse
    this.voronoi.setSites([{x:0,y:0}]);
    this.diagram = this.voronoi.compute(this.bbox);
    this.updateStats();
    },
  randomSites: function(n,clear) {
    // create vertices
    var xo = this.margin;
    var dx = this.canvas.width-this.margin*2;
    var yo = this.margin;
    var dy = this.canvas.height-this.margin*2;
    var vertices = [];
    for (var i=0; i<n; i++) {
      	vertices.push({x:self.Math.round(xo+self.Math.random()*dx),y:self.Math.round(yo+self.Math.random()*dy)});
      }
    // make sites from vertices and compute resulting Voronoi diagram
    if (clear) {
      this.voronoi.setSites(vertices);
      }
    else {
      this.voronoi.addSites(vertices);
      }
    this.diagram = this.voronoi.compute(this.bbox);
    this.updateStats();
    },
  addSite: function(x,y) {
    this.voronoi.addSites([{x:x,y:y}]);
    this.diagram = this.voronoi.compute(this.bbox);
    this.updateStats();
    },
  updateStats: function() {
    if (!this.diagram) {return;}
    var e = document.getElementById('voronoiStats');
    if (!e) {return;}
    e.innerHTML = this.diagram.cells.numCells+' Voronoi cells computed from '+this.diagram.sites.length+' Voronoi sites in '+this.diagram.execTime+' ms (rendering not included.)';
    },
  render: function() {
    var canvas = this.canvas;
    if (!canvas || !canvas.getContext) {return;}
    var ctx = canvas.getContext('2d');
    // background
    ctx.globalAlpha = 1;
    ctx.beginPath();
    ctx.rect(0,0,canvas.width,canvas.height);
    ctx.fillStyle = '#fff';
    ctx.fill();
    ctx.strokeStyle = '#888';
    ctx.stroke();
    // voronoi
    if (!this.diagram) {return;}
    // edges
    ctx.strokeStyle='#000';
    ctx.beginPath();
    var edges = this.diagram.edges;
    var nEdges = edges.length;
    if (nEdges) {
      var edge, v;
      for (var iEdge=nEdges-1; iEdge>=0; iEdge-=1) {
        edge = edges[iEdge];
        v = edge.va;
        ctx.moveTo(v.x,v.y);
        v = edge.vb;
        ctx.lineTo(v.x,v.y);
        }
      ctx.stroke();
      }
    // sites
    var sites = this.diagram.sites;
    var nSites = sites.length;
    if (!nSites) {return;}
    // first, highlight cell under mouse
    if (canvas.onmousemove) {
      var cell = this.diagram.cells[this.diagram.sites[0].id];
      // there is no guarantee a Voronoi cell will exist for any
      // particular site
      if (cell !== undefined) {
        var halfedges = cell.halfedges;
        var nHalfedges = halfedges.length;
        var v = halfedges[0].getStartpoint();
        ctx.beginPath();
        ctx.moveTo(v.x,v.y);
        for (var iHalfedge=0; iHalfedge<nHalfedges; iHalfedge++) {
          v = halfedges[iHalfedge].getEndpoint();
          ctx.lineTo(v.x,v.y);
          }
        ctx.fillStyle = '#faa';
        ctx.fill();
        }
      }
    // then we can draw sites
    ctx.strokeStyle='#800';
    ctx.beginPath();
    for (var iSite=nSites-1; iSite>=0; iSite-=1) {
      v = sites[iSite];
      ctx.rect(v.x-0.5,v.y-0.5,1,1);
      }
    ctx.stroke();
    },
  normalizeEventCoords: function(e) {
    if (!e) {e=self.event;}
    if (e.offsetX !== undefined) {return {x:e.offsetX,y:e.offsetY};}
    var x = e.pageX;
    var y = e.pageY;
    var o = this.canvas;
    do {
      x -= o.offsetLeft;
      y -= o.offsetTop;
      o = o.offsetParent;
    } while (o);
    return {x:x,y:y};
    },
  addLoadEvent: function(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {window.onload = func;}
    else {window.onload = function(){if(oldonload){oldonload();}func();};}
    },
  };
voronoiDemo.addLoadEvent(function(){voronoiDemo.init()});
// -->
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.raymondhill.net/blog/?feed=rss2&#038;p=9</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

