<?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>Azavea Labs &#187; SQL</title>
	<atom:link href="http://www.azavea.com/blogs/labs/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.azavea.com/blogs/labs</link>
	<description>Insight on what our engineers are doing</description>
	<lastBuildDate>Mon, 06 Feb 2012 22:32:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Distance? Math? What?</title>
		<link>http://www.azavea.com/blogs/labs/2009/04/distance-math-what/</link>
		<comments>http://www.azavea.com/blogs/labs/2009/04/distance-math-what/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 18:52:21 +0000</pubDate>
		<dc:creator>Carissa Brittain</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[IDL]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=31</guid>
		<description><![CDATA[A few days ago, I became painfully aware that the distance equation we all learn in geometry class, while it works perfectly well on flat, local projections,  is woefully inadequate when we&#8217;re talking about global coordinate systems. In the midst of implementing Google Maps in our up-coming Sajara sample application, I realized that the International [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago, I became painfully aware that the distance equation we all learn in geometry class, while it works perfectly well on flat, local projections,  is woefully inadequate when we&#8217;re talking about global coordinate systems.</p>
<p>In the midst of implementing <a title="Google Maps API" href="http://code.google.com/apis/maps/documentation/index.html" target="_blank">Google Maps</a> in our up-coming <a title="Sajara Product Site" href="http://www.azavea.com/Products/Sajara/Home.aspx" target="_blank">Sajara</a> sample application, I realized that the <a title="Wikipedia: IDL" href="http://en.wikipedia.org/wiki/International_Date_Line" target="_blank">International Date Line</a> was causing problems. Large problems. Whenever the IDL was <a title="Play Ball!" href="http://en.wikipedia.org/wiki/List_of_baseball_jargon_(I)#in_play">in play</a>, I never retrieved the correct results from our database. One large problem was how we defined our <a title="Openlayers bounding box" href="http://dev.openlayers.org/apidocs/files/OpenLayers/BaseTypes/Bounds-js.html#OpenLayers.Bounds">bounding box</a> inside Sajara itself. Once that was fixed, however, I realized that something was still wrong. The Nearest-to-Farthest sort was not behaving quite right: it was really doing a Nearest-on-this-side-of-the-IDL-first sort! The IDL was acting like a <a href="http://en.wikipedia.org/wiki/Hadrian%27s_wall">wall</a> for our distance sort.</p>
<div id="attachment_39" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-39" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2009/04/distance-300x234.gif" alt="distance" width="300" height="234" /><p class="wp-caption-text">Example of linear distance with IDL in play. X = center of map</p></div>
<p style="text-align: center">
<p>Here&#8217;s what we used before (in <a title="Transact SQL" href="http://en.wikipedia.org/wiki/TSQL">sql-speak</a>):</p>
<pre><span style="color: #800000">RETURN sqrt(power(@FromX - @ToX,2) + power(@FromY - @ToY,2))</span></pre>
<p>Your standard square-root of difference-squared plus difference-squared. This formula is fast and worked perfectly well so long as I operated under these two criteria:</p>
<p>1. a FLAT <a href="http://en.wikipedia.org/wiki/Map_projection">projection</a><br />
2. POSITIVE numbers only</p>
<p>Once either of those things aren&#8217;t true anymore, I can&#8217;t use the basic distance formula. In my case, both things stopped being true at the same time! The solution? Something fairly math-magical to my mind, but accepted as THE formula to get at the distance between any two global coordinates: the <a title="Haversine Formula" href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine Formula</a>. Delving into descriptions of the formula brings up concepts such as <a href="http://mathworld.wolfram.com/SphericalTriangle.html">spherical triangles</a>, the planet&#8217;s <a title="Elipticity" href="http://en.wikipedia.org/wiki/Ellipsoid">elipticity</a>, <a title="Great Circles" href="http://en.wikipedia.org/wiki/Great_circle">great circles</a> and other things very important to <a title="Polynesian Navigation" href="http://www.teara.govt.nz/NewZealanders/MaoriNewZealanders/CanoeNavigation/2/en">navigation</a>. It&#8217;s accurate down to about a meter, which is plenty for anything I&#8217;ll be doing with it.</p>
<p>Haversine Formula <a title="javascript implementation" href="http://www.movable-type.co.uk/scripts/latlong.html">in Javascript</a>:</p>
<pre style="margin-left: 0pt"><span style="color: #800000">var R = 6371; // radius of the earth
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var distance = R * c;</span></pre>
<p>So here is the resulting SQL function that gives me the right distance between any two global coordinates.. basically a direct translation of the above javascript into T-SQL:</p>
<pre style="margin-left: 0pt"><span style="color: #800000">CREATE FUNCTION [dbo].[distance] (@FromX float, @FromY float, @ToX float, @ToY float)
RETURNS float AS BEGIN
DECLARE @R AS FLOAT;
SET @R = 6371;
DECLARE @DLAT AS FLOAT;
DECLARE @DLON AS FLOAT;
DECLARE @A AS FLOAT;
DECLARE @C AS FLOAT;
DECLARE @D AS FLOAT;
SET @DLAT = RADIANS(@ToY - @FromY);
SET @DLON = RADIANS(@ToX - @FromX);
SET @A =
SIN(@DLAT/2) * SIN(@DLAT/2) +
COS(RADIANS(@FromY)) * COS(RADIANS(@ToY)) * SIN(@DLON/2) * SIN(@DLON/2);
SET @C = 2 * ATN2(SQRT(@A), SQRT(1-@A));
SET @D = @R * @C;
RETURN @D
END</span></pre>
<p><a title="http://en.wikipedia.org/wiki/Haversine_formula " href="http://en.wikipedia.org/wiki/Haversine_formula" target="_blank"><br />
</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2009/04/distance-math-what/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

