<?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:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>MapWrecker 2.0</title>
	<atom:link href="http://mapwrecker.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://mapwrecker.wordpress.com</link>
	<description>AJAX, Maps, .NET, and Destruction</description>
	<pubDate>Tue, 17 Jun 2008 15:49:43 +0000</pubDate>
	<generator>http://wordpress.org/?v=MU</generator>
	<language>en</language>
			<item>
		<title>Disruptive Egotism</title>
		<link>http://mapwrecker.wordpress.com/2008/06/17/disruptive-egotism/</link>
		<comments>http://mapwrecker.wordpress.com/2008/06/17/disruptive-egotism/#comments</comments>
		<pubDate>Tue, 17 Jun 2008 15:49:43 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[Destruction]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=57</guid>
		<description><![CDATA[I just read the VerySpatial post linking to Builder.com Ten Commandments of Egoless Programming via TheSteve0.  VerySpatial likes Commandment #3: No matter how much “karate” you know, someone else will always know more. 
I like this one too, but for very different reasons.  This rule, to me, is a signpost showing where ego can be put to use:  disruptive technologies.  In essence, if [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I just read the <a href="http://veryspatial.com/?p=2169">VerySpatial</a> post linking to <a href="http://articles.techrepublic.com.com/5100-10878_11-1045782.html">Builder.com Ten Commandments of Egoless Programming</a> via <a href="http://thesteve0.wordpress.com/"><span style="color:#999966;">TheSteve0</span></a>.  VerySpatial likes Commandment #3: <strong><em>No matter how much “karate” you know, someone else will always know more.</em></strong> </p>
<p>I like this one too, but for very different reasons.  This rule, to me, is a signpost showing where ego can be put to use:  disruptive technologies.  In essence, if no matter how good you are, someone will always be better: <strong><em>then change the game.</em></strong> </p>
<p>My other favorite?:<strong><em> The only constant in the world is change</em></strong>.   Keep your ego.  Lead.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/57/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/57/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/57/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/57/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/57/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=57&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/06/17/disruptive-egotism/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Tiny Flex/AS3 XML Settings Loader</title>
		<link>http://mapwrecker.wordpress.com/2008/05/19/tiny-flexas3-xml-settings-loader/</link>
		<comments>http://mapwrecker.wordpress.com/2008/05/19/tiny-flexas3-xml-settings-loader/#comments</comments>
		<pubDate>Mon, 19 May 2008 07:05:56 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[AJAX]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=56</guid>
		<description><![CDATA[I have been writing a lot of Flex code recently.
Somehow, I&#8217;m most pleased with this *tiny* little class to load XML settings from the HTML container.  
The joy here is that Flash/Flex can *only* load data asynchronously&#8230; this class allows settings to be pulled in sychronously, before anything else, and with very little effort.



package [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I have been writing a lot of Flex code recently.<br />
Somehow, I&#8217;m most pleased with this *tiny* little class to load XML settings from the HTML container.  </p>
<p>The joy here is that Flash/Flex can *only* load data asynchronously&#8230; this class allows settings to be pulled in sychronously, before anything else, and with very little effort.</p>
<div style="overflow:scroll;width:100%;text-align:left;">
<pre>
<code>
package com.wordpress.mapwrecker
{
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;
	import flash.external.ExternalInterface;

	dynamic public class Settings extends Proxy {
		private var data:XML;

		public function Settings() {
			//load settings from parent HTML document
			if(ExternalInterface.available)
			{
				 var getSettingsRequest:String = "function(){ return document.getElementById(\"settings\").innerHTML; }";
				 var response:String = ExternalInterface.call(getSettingsRequest);
				 data = XML(response);
			}
		}

		override flash_proxy function getProperty(name:*):* {
			return data.children().(localName().toUpperCase() == String(name).toUpperCase());
		}
	}

}
</code>
</pre>
</div>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/56/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/56/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/56/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/56/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/56/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=56&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/05/19/tiny-flexas3-xml-settings-loader/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Using Mercator Tiles in ESRI&#8217;s ArcWeb Flex API</title>
		<link>http://mapwrecker.wordpress.com/2008/04/28/using-mercator-tiles-in-esris-arcweb-flex-api/</link>
		<comments>http://mapwrecker.wordpress.com/2008/04/28/using-mercator-tiles-in-esris-arcweb-flex-api/#comments</comments>
		<pubDate>Mon, 28 Apr 2008 21:56:33 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=55</guid>
		<description><![CDATA[I extended ESRI&#8217;s ArcWeb Flex API&#8217;s RasterTileLayer class which normally supports only geographic tile layouts, and made it work with Mercator.  Picture a lot of trial and error, and a few functioning yet not working tile-layouts that were plain silly. 
ESRI&#8217;s ArcWeb Flex API supports making web maps from ArcWeb data-sources and from some custom data-sources [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I extended ESRI&#8217;s ArcWeb Flex API&#8217;s RasterTileLayer class which normally supports only geographic tile layouts, and made it work with Mercator.  Picture a lot of trial and error, and a few functioning yet not working tile-layouts that were plain silly. </p>
<p>ESRI&#8217;s ArcWeb Flex API supports making web maps from ArcWeb data-sources and from some custom data-sources such as ArcIMS and ArcGIS Server.  A couple of code-samples infer that writing your own custom imagery provider is easy.  But I wouldn&#8217;t call it easy.  The ArcWeb Flex API is closed source, the documentation extends only to public methods/properties, and does not cover all classes in the API.</p>
<p>Luckily, there are ways of digging.  The Flex API ships as an SWC file &#8212; a compiled Flash/Flex library.  These files are well known to be ZIP files containing a CATALOG.XML file.  This catalog file lists all of the class names in the API along with dependency classes.  Its a more convenient way of getting to know the hidden API than blindly exploring the &#8220;import com.esri.awx&#8230;&#8221; intellisense code-hints available within Flex Builder.</p>
<p>Once you&#8217;ve found an interesting class, cross your fingers and pray that its implementation is obvious.  Again, code-hinting goes a long way.  Its trivial to instantiate a class and see what public methods and properties are available.  Sub-class using the &#8221;extends&#8221; keyword and you&#8217;ll gain access to the internal and protected property and method names.  Within the Flex API, the class names, code-hinting, etc. are usually descriptive enough to get by.</p>
<p>When the path is less clear, you&#8217;ll need to use Flex&#8217;s debugging to find your way.  I eventually sub-classed and overrode every class method/getter/setter with a simple call to the super-class.  This allowed me to follow the logical order of method calls, and keep an eye on the Flex debug Variables at every step of the class&#8217;s lifecycle.</p>
<p>Did I mention trial-and-error?  I still don&#8217;t know how or why some of the code I wrote works.  To me, the math hacks are what makes this cool &#8230; we say the earth is 360&#215;360 to make things square, but fudge the latitude to fix tile Y-positioning.</p>
<div style="overflow:scroll;width:100%;text-align:left;"><code>
<pre>

package com.esri.aws.awx.map.layers
{
	import com.esri.aws.awx.map.projection.*;
	import com.esri.aws.awx.map.layers.tiles.*;

	public class MercatorTileLayer extends RasterTileLayer
	{
		private var _mercLayout : ITileLayout;

		public function MercatorTileLayer()
		{
			m_scheme =  new ClientPowerOfTwoTilingSchemeImpl(true, 17, 256, 256, 1, 1, -180, -180, 180, 180, "");
			m_tileLayout = _mercLayout = new MercatorTileLayout(m_scheme);
		}

		override protected function commitProperties():void{
			m_schemes[dataSource] = m_scheme; // setting m_schemes[] seems to prevent m_scheme resets
			super.commitProperties(); // This still resets m_tileLayout, I can't figure a way around it
			m_tileLayout = _mercLayout; // So we'll fix m_tileLayout ourselves
        }

		override public function get supportedProjections():Array
		{
			return [ProjUtils.PROJECTION_STYLE_MERCATOR];
		}

		override protected function constructUrl(tileKey:TileKey, token:String):String{
			return "http://localhost./TileServer/" + dataSource + "/" + getZoomString( tileKey ) + ".ashx";
		}

	}
}
</pre>
<p></code></div>
<div style="overflow:scroll;width:100%;text-align:left;"><code>
<pre>

package com.esri.aws.awx.map.layers.tiles
{
	public class MercatorTileLayout extends TileLayoutImpl implements ITileLayout
	{
		internal static var toDegrees:Number = 180.0 / Math.PI;
		internal static var toRadians:Number = Math.PI / 180.0; 

		public function MercatorTileLayout(tilingScheme:ITilingScheme)
		{
			super(tilingScheme);
		}

		override public function determineTilesForView(list:TilesList, centerX:Number, centerY:Number, mapScale:Number, displayWidth:int, displayHeight:int):TilesList
		{
			if (centerY &gt; 85.05113) centerY = 85.05113;
			if (centerY &lt; -85.05113) centerY = -85.05113;

			centerY = centerY * toRadians;
			centerY = Math.log( Math.abs(Math.tan( (Math.PI/4) + (centerY/2) )) );
			centerY = centerY * toDegrees;

			return super.determineTilesForView(list, centerX, centerY, mapScale, displayWidth, displayHeight);
		}

	}
}
</pre>
<p></code></div>
<p>One final note is that this won&#8217;t get you too far using Google or Microsoft&#8217;s Mercator tiles.  Flash famously has the ability to bypass cross-domain restrictions using CrossDomain.xml files.  Lesser known is Flash&#8217;s lameness in using images across domains.  You oddly cannot smooth/resize/alter an image loaded from another domain without a CrossDomain.xml file.  The Flex API does image smoothing and resizing, so no-go for commercial imagery providers without crossdomain.xml files.  Ridiculous!</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/55/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/55/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/55/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=55&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/04/28/using-mercator-tiles-in-esris-arcweb-flex-api/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting &#8220;localhost.&#8221; to work with IIS7</title>
		<link>http://mapwrecker.wordpress.com/2008/03/09/getting-localhost-to-work-with-iis7/</link>
		<comments>http://mapwrecker.wordpress.com/2008/03/09/getting-localhost-to-work-with-iis7/#comments</comments>
		<pubDate>Sun, 09 Mar 2008 09:16:38 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=51</guid>
		<description><![CDATA[I&#8217;m not 100% sure why, but with IIS7, I am unable to get connect to my local IIS instance using Fiddler&#8217;s magic &#8220;localhost.&#8221; hostname.   Normally this hostname allows localhost traffic to be monitored within Fiddler.  Out of the box, IIS7 was returning me the following error on requests to &#8220;localhost.&#8221;:
Bad Request - Invalid [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;m not 100% sure why, but with IIS7, I am unable to get connect to my local IIS instance using Fiddler&#8217;s magic &#8220;localhost.&#8221; hostname.   Normally this hostname allows localhost traffic to be monitored within Fiddler.  Out of the box, IIS7 was returning me the following error on requests to &#8220;localhost.&#8221;:</p>
<p>Bad Request - Invalid Hostname</p>
<p>Trying to add a secondary binding with &#8220;localhost.&#8221; explicitly set as the host yeilds another error, this time from the IIS Management Console:</p>
<p>Value does not fall within the expect range.</p>
<p>I found that editing Fiddler&#8217;s CustomRules.js provides a quick workaround while still allowing you to use the exact &#8220;localhost.&#8221; name.   Simply add the following line to the &#8220;onBeforeRequest&#8221; function:</p>
<p>if (oSession.host.ToUpper() == &#8220;LOCALHOST.&#8221;) { oSession.host = &#8220;localhost&#8221;; }</p>
<p>This fix of course only works when Fiddler is running, so please comment if you know of a workaround within IIS7.  (Alternatively, please comment if you have no issue in IIS7 &#8212; that my box simply has a case of the Vistas.)</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/51/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/51/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/51/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=51&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/03/09/getting-localhost-to-work-with-iis7/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Deconstructing Mercator, Part 2</title>
		<link>http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator-part-2/</link>
		<comments>http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator-part-2/#comments</comments>
		<pubDate>Sat, 01 Mar 2008 06:50:16 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[Mercator]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=49</guid>
		<description><![CDATA[Summarizing last time:  Google&#8217;s WKT includes SPHEROID[”…”, 6378137, 0], meaning the earth is a sphere with a radius of 6378137 meters. 6378137 * pi = 20037508, the half-circumference of the earth in meters, and the Mercator max range.  Solve the Mercator equations so that max X = max Y, and you&#8217;ll find that happens at +/- 85.051 degrees latitude.
Notice [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Summarizing <a href="http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator/">last time</a>:  Google&#8217;s WKT includes SPHEROID[”…”, 6378137, 0], meaning the earth is a sphere with a radius of 6378137 meters. 6378137 * pi = 20037508, the half-circumference of the earth in meters, and the Mercator max range.  Solve the <a href="http://en.wikipedia.org/wiki/Mercator_projection">Mercator</a> equations so that max X = max Y, and you&#8217;ll find that happens at +/- 85.051 degrees latitude.</p>
<p>Notice this 85.051 degrees is a &#8220;magic number&#8221; in Mercator; it dictates a perfect Mercator square for the moon as well as it does the Earth.  Our WKT says Google&#8217;s Mercator maps are based on meters.  Yet <a href="http://en.wikipedia.org/wiki/Mercator_projection">Wikipedia&#8217;s math</a> imagines a world with a radius of 1.  Worse, Charlie rightly points out that Google&#8217;s APIs also <a href="http://cfis.savagexi.com/articles/2006/05/03/google-maps-deconstructed">imagines multiple Mercator worlds</a> with various pixel dimensions!</p>
<p>In short, there is only one square Mercator projection of a sphere.  Datum is the question.  Your local WMS/IMS may need to know the earth is 6378137 meters in radius for conversion from other projections.  One the other hand, it&#8217;d be happy with 6378.137 km, 31795.5 furlongs, or 6.7418e-10 lightyears, as long as you can explain the relationship.  {You can tweak your WKT SPHEROID all day, as long as you equally modify your DATUM&#8217;s UNIT values.}</p>
<p>More to the point, no matter what your datum, there is only one defacto tile standard: 256&#215;256 tiles, a 256&#215;256 base map, n zoom levels, and a 2&#215;2 zoom between levels.  With tiles, the earth is 128*2^n/pi pixels in radius, end of story.  Any Mercator datum can be turned into another simply by multiplying by the ratio of their diameters.  Making a 6378137 m radius earth fit into 256&#215;256 pixels is one such transformation of datum.</p>
<p>The fun thing, then, is coming up with a better datum.  Google&#8217;s solution of pixel datums is certainly elegant.  In many circumstances, however, we are trying to fit tiles to geographic coordinates.  Here, a 360&#215;360 unit Mercator Earth is a nice, clean option. </p>
<p>Remember that the Mercator projection does not touch longitude except for datum conversion.  Hence, with a 360&#215;360 Mercator Earth, longitude is equal to X already.  Mercator Y can be derived from latitude using the simple { Y = log( tan( lat ) + sec( lat ) ) } equation.</p>
<p>And that&#8217;s Mercator.   Fin.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/49/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/49/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/49/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/49/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/49/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/49/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/49/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/49/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/49/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/49/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/49/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/49/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=49&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator-part-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Deconstructing Mercator</title>
		<link>http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator/</link>
		<comments>http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator/#comments</comments>
		<pubDate>Sat, 01 Mar 2008 02:42:28 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[Mercator]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=48</guid>
		<description><![CDATA[These days, everybody uses mercator tilesets.  Charlie and Morten both put forth excellent explanation of Mercator for us.  These two are both smart, smart guys.  I will attempt to give an unsmart explanation.
If you were to take a globe and count its degrees, you&#8217;d see the earth is 360 degrees around, and 180 degrees from pole to [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>These days, <a href="http://maps.yahoo.com/">everybody</a> uses <a href="http://maps.google.com/">mercator</a> <a href="http://maps.live.com/">tilesets</a>.  <a href="http://cfis.savagexi.com/articles/2006/05/03/google-maps-deconstructed">Charlie</a> and <a href="http://www.sharpgis.net/post/2007/07/26/The-Microsoft-Live-Maps-and-Google-Maps-projection.aspx">Morten</a> both put forth excellent explanation of <a href="http://en.wikipedia.org/wiki/Mercator_projection">Mercator</a> for us.  These two are both smart, smart guys.  I will attempt to give an unsmart explanation.</p>
<p>If you were to take a globe and count its degrees, you&#8217;d see the earth is 360 degrees around, and 180 degrees from pole to pole.  Easy!!  A circle&#8217;s circumference is 360 degrees, and also its radius * 2 * pi.  By that logic, 180 degrees = pi * r, and the earth is pi*r tall, and 2*pi*r wide.</p>
<p>Knowing the earth&#8217;s radius, then, we can calculate the circumference of the earth (2*pi*r).  The trick is, not everybody is willing to say that the earth is a sphere.  People who know fancy words are more inclined to describe our earth as an <a href="http://en.wikipedia.org/wiki/Oblate_spheroid">oblate spheroid</a> &#8212; a somewhat flattened sphere. </p>
<p>Morten&#8217;s WKTs inform us that WGS84 uses a spheroid of SPHEROID["...",6378137, 298.257223563] while Google uses a spheroid of SPHEROID["...", 6378137, 0].  It&#8217;s that third parameter thats interesting:  its the <a href="http://en.wikipedia.org/wiki/Oblate_spheroid">flattening</a> factor.  It means WGS84 knows the earth is an oblate spheroid, while Google treats the earth as a perfect sphere.  6378137 meters is the semi-major axes of WGS84&#8217;s oblate world.  In Google&#8217;s world view, this number is simply the radius of the earth.</p>
<p>Sweet.  We know the radius of the Google&#8217;s earth.  We know the half-circumference of the earth, too, pi*r:  20037508.342789 meters.  Check the validMercator range for the Google projection and you&#8217;ll see a pattern:  [-20037508.3427892, -20037508.3427892] to [20037508.3427892, 20037508.3427892].  Morten is simply telling us that Google uses the circumference of the earth in meters!!</p>
<p> But WAIIIIT.   The earth is pi*r tall, and 2*pi*r wide.  Half of those numbers should be half that!!  And they would be, in an <a href="http://en.wikipedia.org/wiki/Plate_carr%C3%A9e_projection">unprojected/plate carre</a> world; but Google uses a <a href="http://en.wikipedia.org/wiki/Mercator_projection">Mercator</a> projection.  Referring to Wikipedia and our valid range, we can see that Mercator is happy to leave longitude alone.  But also from Wikipedia, &#8220;A Mercator map can never fully show the polar areas, since linear scale becomes infinitely high at the poles.&#8221;</p>
<p> WHAT?  Yes, Mercator project has an infinite Y range.  We can&#8217;t have infinite bounds!! So how does Google make it look like a square?  Simple:  they chop off the poles. </p>
<p>For simplicity&#8217;s sake, put your mental trig calculator into degree mode, or pretend the world has a radius of 1.  Take Wikipedia&#8217;s Mercator projection  { Y = log( tan( lat ) + sec( lat ) ) },  and solve with Y = 180.  You&#8217;ll arrive at a value of 85.051 degrees &#8230; which should again be familiar from Morten&#8217;s blog.  85.051 degrees is a magic latitude that gives Google their square earth.</p>
<p>So there you go:  A rough explanation of Mercator, and an only slightly better explanation of some of the WKT magic number behind hit.  Stay tuned for <a href="http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator-part-2/">part two</a>.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/48/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/48/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/48/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=48&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/03/01/deconstructing-mercator/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Back in Black</title>
		<link>http://mapwrecker.wordpress.com/2008/03/01/back-in-black/</link>
		<comments>http://mapwrecker.wordpress.com/2008/03/01/back-in-black/#comments</comments>
		<pubDate>Sat, 01 Mar 2008 00:50:37 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[Destruction]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=47</guid>
		<description><![CDATA[Last June I noticed that most of my blog posts were comparisons, to which I attributed a sort of kitsch.
Kitsch, according to Milan Kundera&#8217;s book The Unbearable Lightness of Being, defined it as &#8220;the absolute denial of shit.&#8221; I hoped to poke some fun at the GIS programmers&#8217; feuding over paradigms / languages / libraries by presenting [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Last June I noticed that most of my blog posts were comparisons, to which I attributed a sort of kitsch.</p>
<p>Kitsch, according to Milan Kundera&#8217;s book <a href="http://books.google.com/books?id=Zd1l0Ivij8wC&amp;dq=the+unbearable+lightness+of+being&amp;pg=PP1&amp;ots=6CUO2-gt4u&amp;sig=dLysik-7n7-vSFVvoK3yV0sXido&amp;hl=en&amp;prev=http://www.google.com/search?q=the+unbearable+lightness+of+being&amp;rls=com.microsoft:en-us:IE-SearchBox&amp;ie=UTF-8&amp;oe=UTF-8&amp;sourceid=ie7&amp;rlz=1I7ADBF&amp;sa=X&amp;oi=print&amp;ct=title&amp;cad=one-book-with-thumbnail">The Unbearable Lightness of Being</a>, defined it as &#8220;the absolute denial of shit.&#8221; I hoped to poke some fun at the GIS programmers&#8217; feuding over paradigms / languages / libraries by presenting a world-view like Kundera&#8217;s kitsch, where <a href="http://www.websters-online-dictionary.org/ki/kitsch.html">&#8220;all answers are given in advance and preclude any questions.&#8221;  </a></p>
<p>Hence <a href="http://mapwrecker.wordpress.com/2007/06/07/mapwrecker-20-change-vs-progress/">I embraced a cloying battle meme</a>, and elevated my level of distasteful sarcasm.  Today, I&#8217;ve finally grown tired of this faux personality, and have accumulated a few ideas I&#8217;d like to post in a more traditional format.  In other words, I&#8217;m going back to normal.  Wish me luck.</p>
<p>PS:  WordPress&#8217;s spell check doesn&#8217;t recognize the word &#8220;blog&#8221;. &#8220;Biog&#8221; and &#8220;bldg&#8221; are suggested alternatives.  Just a note for anyone hoping my sarcasm would disappear overnight.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/47/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/47/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/47/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/47/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/47/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/47/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/47/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/47/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/47/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/47/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/47/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/47/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=47&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/03/01/back-in-black/feed/</wfw:commentRss>
		</item>
		<item>
		<title>ArcGIS Server Virtual Earth Tile Server vs. ArcIMS</title>
		<link>http://mapwrecker.wordpress.com/2008/02/04/arcgis-server-virtual-earth-tile-server-vs-arcims/</link>
		<comments>http://mapwrecker.wordpress.com/2008/02/04/arcgis-server-virtual-earth-tile-server-vs-arcims/#comments</comments>
		<pubDate>Mon, 04 Feb 2008 21:20:53 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[ArcGIS Server]]></category>

		<category><![CDATA[ArcIMS]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=46</guid>
		<description><![CDATA[Time to change the name Dave.


     

using System;
using System.Text;
using ArcDeveloper.TileServer.Interfaces;
using System.Net;
using System.IO;
using System.Xml;
using System.Drawing;
using System.Drawing.Imaging;   

namespace ArcDeveloper.TileServer.ArcIMS
{
    public class ArcImsTileProvider : ITileProvider
    {
        ///
        /// Private member containing the [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://blog.davebouwman.net/2008/02/03/ArcGISServerVirtualEarthTileServerV01ReleaseNotes.aspx">Time to change the name Dave.</a></p>
<div style="overflow:scroll;width:100%;text-align:left;">
<pre>
<code>     

using System;
using System.Text;
using ArcDeveloper.TileServer.Interfaces;
using System.Net;
using System.IO;
using System.Xml;
using System.Drawing;
using System.Drawing.Imaging;   

namespace ArcDeveloper.TileServer.ArcIMS
{
    public class ArcImsTileProvider : ITileProvider
    {
        ///
        /// Private member containing the web service url
        ///
        private string _webServiceUrl = "";   

        ///
        /// Constructor that takes a web service Url
        ///
        ///
        public ArcImsTileProvider(string webServiceUrl)
        {
            _webServiceUrl = webServiceUrl;
        }   

        ///
        /// Get the tile image
        ///
        ///
        ///
        ///
        /// Tile data stream
        public System.IO.MemoryStream GetTile(ITileExtent extent, int tileHeight, int tileWidth)
        {
            MemoryStream returnStream = null;   

            try
            {
                string axl = getAXL(extent, tileHeight, tileWidth);
                Stream responseStream = PostData(_webServiceUrl, axl);
                XmlDocument xd = new XmlDocument();
                xd.Load(responseStream);
                string imgURL = xd.GetElementsByTagName("OUTPUT")[0].Attributes["url"].Value;
                responseStream.Close();   

                Bitmap bm = new Bitmap(new WebClient().OpenRead(imgURL));
                returnStream = new MemoryStream();
                bm.Save(returnStream, ImageFormat.Png);
            }
            catch(Exception e)
            {
                Bitmap bm = GetMessageTile(e.Message);
                returnStream = new MemoryStream();
                bm.Save(returnStream, ImageFormat.Png);
            }   

            return returnStream;
        }   

        ///
        /// Gets the ArcIMS GetImage AXL request.
        ///
        ///
        ///
        ///
        /// GetImage ArcIMS AXL request
        private string getAXL(ITileExtent extent, int tileHeight, int tileWidth)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("&lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?&gt;");
            sb.Append("&lt;ARCXML version=\"1.1\"&gt;");
            sb.Append("&lt;REQUEST&gt;");
            sb.Append("&lt;GET_IMAGE&gt;");
            sb.Append("&lt;PROPERTIES&gt;");
            sb.Append("&lt;ENVELOPE minx=\"" + extent.lon2 + "\" miny=\"" + extent.lat2 + "\" maxx=\"" + extent.lon + "\" maxy=\"" + extent.lat + "\" /&gt;");
            sb.Append("&lt;IMAGESIZE height=\"" + tileHeight + "\" width=\"" + tileWidth + "\" /&gt;");
            sb.Append("&lt;/PROPERTIES&gt;");
            sb.Append("&lt;/GET_IMAGE&gt;");
            sb.Append("&lt;/REQUEST&gt;");
            sb.Append("&lt;/ARCXML&gt;");
            return sb.ToString();
        }   

        ///
        /// Gets a tile with an error message burned into it.
        ///
        /// The message.
        /// An error message PNG
        private Bitmap GetMessageTile(string message)
        {
            Bitmap tile = new Bitmap(Properties.Resources.blankTile);
            Graphics graphics = Graphics.FromImage(tile);
            Font drawFont = new Font("Arial", 12);
            SolidBrush drawBrush = new SolidBrush(System.Drawing.Color.Black);
            SizeF len = graphics.MeasureString(message, drawFont);
            graphics.DrawString(message, drawFont, drawBrush, new PointF(10, 10));
            graphics.Dispose();
            return tile;
        }   

        ///
        /// Does an HTTP Post, returning a stream.
        ///
        /// The URL to post to
        /// The data to post
        /// The Http response stream
        private Stream PostData(string sURL, string postData)
        {
            HttpWebRequest webReq = null;
            HttpWebResponse response = null;
            Stream requestStream = null;
            StreamWriter writer = null;
            Stream responseStream = null;
            try
            {
                webReq = (HttpWebRequest)WebRequest.Create(sURL);
                webReq.Method = "POST";
                webReq.ContentType = "application/x-www-form-urlencoded";
                webReq.Timeout = 0xea60;
                webReq.AllowAutoRedirect = true;
                requestStream = webReq.GetRequestStream();
                writer = new StreamWriter(requestStream);
                writer.Write(postData);
                writer.Flush();
                writer.Close();
                requestStream.Close();
                response = (HttpWebResponse)webReq.GetResponse();
                responseStream = ((HttpWebResponse)webReq.GetResponse()).GetResponseStream();
            }
            finally
            {
                if (writer != null) writer.Close();
            }
            return responseStream;
        }   

    }
}   

</code></pre>
</div>
<p><strong>Winners:</strong> <a href="http://www.tilecache.org/">Python-fearing</a> .NET folks still using ArcIMS.  All six of you!</p>
<p><strong>Losers:</strong> &#8220;ArcGIS Server Virtual Earth Tile Server&#8221; as a name.  Die.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/46/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/46/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/46/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=46&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/02/04/arcgis-server-virtual-earth-tile-server-vs-arcims/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Well Known Vs. Rational Vector Delivery - Part 3</title>
		<link>http://mapwrecker.wordpress.com/2008/02/01/well-known-vs-rational-vector-delivery-part-3/</link>
		<comments>http://mapwrecker.wordpress.com/2008/02/01/well-known-vs-rational-vector-delivery-part-3/#comments</comments>
		<pubDate>Fri, 01 Feb 2008 18:08:54 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[Vector Clients]]></category>

		<category><![CDATA[Vectors]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/?p=45</guid>
		<description><![CDATA[It looks like the boys at Microsoft Research implemented my idea: tiled vectors.  Their demo makes one thing obvious, however.  Douglas-Peucker just doesn&#8217;t cut it for topologies.  This becomes a non-issue with a pixel-level of detail, but just looks bad in their demo.  Their implementation doesn&#8217;t seem to preserve existing points between zooms; it&#8217;s probably just as [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>It looks like the boys at Microsoft Research <a href="http://research.microsoft.com/MapCruncher/TiledVectors/TiledVectorsDemo-1.1/description.html">implemented my idea</a>: <a href="http://mapwrecker.wordpress.com/2007/08/24/rational-vector-delivery-pre-game/">tiled vectors</a>.  Their <a href="http://research.microsoft.com/MapCruncher/TiledVectors/TiledVectorsDemo-1.1/">demo</a> makes one thing obvious, however.  Douglas-Peucker just doesn&#8217;t cut it for topologies.  This becomes a non-issue with a pixel-level of detail, but just looks bad in their <a href="http://research.microsoft.com/MapCruncher/TiledVectors/TiledVectorsDemo-1.1/">demo</a>.  Their implementation doesn&#8217;t seem to preserve existing points between zooms; it&#8217;s probably just as efficient this way.  <a href="http://viswaug.wordpress.com/2008/01/21/tiling-vector-data-for-virtualearth-applications/">Via Vish.</a>  (Check out <a href="http://www.idevio.com/demo/webmap/">Idevio</a>, while you&#8217;re at it.) </p>
<p><strong>Winners:</strong>  Me!  Virtual Earth stole my idea!!  (LOL&#8230; &#8220;my&#8221; idea)</p>
<p><strong>Losers:</strong> Me!  Virtual Earth stole my idea!!</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/45/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/45/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/45/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/45/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/45/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=45&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2008/02/01/well-known-vs-rational-vector-delivery-part-3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>LINQ vs LINQ</title>
		<link>http://mapwrecker.wordpress.com/2007/12/19/linq-to-sql-vs-linq-to-objects/</link>
		<comments>http://mapwrecker.wordpress.com/2007/12/19/linq-to-sql-vs-linq-to-objects/#comments</comments>
		<pubDate>Wed, 19 Dec 2007 22:40:55 +0000</pubDate>
		<dc:creator>Bill Thorp</dc:creator>
		
		<category><![CDATA[.NET]]></category>

		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://mapwrecker.wordpress.com/2007/12/19/linq-to-sql-vs-linq-to-objects/</guid>
		<description><![CDATA[I&#8217;m just getting into LINQ, and experimenting with what goes on behind the scenes.  LINQ uses the idea of a &#8220;DataContext&#8221; as an interface to the database, much like the older &#8220;DataSet&#8221; acts to encapsulate multiple table structures.   One notably lacking feature of LINQ&#8217;s database-derived classes is the ability to traverse many-to-many relationships without touching the intermediate cross-reference [...]]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;m just getting into LINQ, and experimenting with what goes on behind the scenes.  LINQ uses the idea of a &#8220;DataContext&#8221; as an interface to the database, much like the older &#8220;DataSet&#8221; acts to encapsulate multiple table structures.   One notably lacking feature of LINQ&#8217;s database-derived classes is the ability to traverse many-to-many relationships without touching the intermediate cross-reference table. </p>
<p>Assuming an existing &#8220;vsNetwork&#8221; entity, you can query a many-to-many relationship directly against the &#8221;DataContext&#8221; ala:</p>
<blockquote><p>from f in myDataContext.ScienceFocus<br />
join vsf in vsDc.VitalSignFocus on f.FocusId equals vsf.FocusIdf<br />
where vsf.VitalSignIdf == vsNetwork.VitalSignId<br />
select f;</p></blockquote>
<p>Again assuming an existing &#8220;vsNetwork&#8221; entity, you can also query by walking the database-derived class&#8217;s table-relations, ala:</p>
<blockquote><p>vsNetwork.FXrefVitalSignFocusList.Select(vsf =&gt; vsf.FTluScienceFocus).ToList();</p></blockquote>
<p>The magic of LINQ exists within all things that implement the IQueriable interface.  This allows the keywords &#8220;select&#8221;, &#8220;where&#8221;, &#8220;join&#8221;, etc. to be applied to a collection of objects.  Note, however, that there are differences in how &#8220;IQueriable&#8221; is implemented.  The examples above, indeed generate markedly different SQL.  Respectively,</p>
<blockquote><p>SELECT [t0].* FROM [tlu_Science_Focus] AS [t0] INNER JOIN [xref_Vital_Sign_Focus] AS [t1] ON [t0].[Focus_ID] = [t1].[Focus_IDF] WHERE [t1].[Vital_Sign_IDF] = <i>vsNetwork.Vital_Sign_ID</i></p></blockquote>
<p>versus</p>
<blockquote><p>SELECT [Focus_IDF] FROM [xref_Vital_Sign_Focus]  WHERE [Vital_Sign_IDF] = <i>vsNetwork.Vital_Sign_ID </i></p>
<p><i>*For Each Focus_IDF&#8230;*</i></p>
<p>SELECT * FROM [tlu_Science_Focus] WHERE [Focus_ID] = <i>Focus_IDF</i></p></blockquote>
<p>We see that the latter runs multiple queries instead of using a SQL join.  The source of this inefficiency is described by <a href="http://blogs.msdn.com/mattwar/archive/2006/05/10/oops-we-did-it-again.aspx">The Wayward Weblog</a>:</p>
<blockquote><p>&#8220;[EntitySet's] ToQueryable() wraps your IEnumerable&lt;T&gt; in IQueryable&lt;T&gt; clothing, uses the Queryable infrastructure to let you build up your own expression tree queries, and then when you enumerate it, the expression is rebound to refer to your IEnumerable&lt;T&gt; directly&#8221;</p></blockquote>
<p>In this case, &#8220;vsNetwork.FXrefVitalSignFocusList&#8221; is of type EntitySet, which does not implement IQueriable directly, but rather through IEnumerable.  So not only does this shorter syntax lose efficiency by issuing multiple and superfluous queries, it also loses efficiency by iterating through each xref table in memory.  In the case of large sets, using LINQ against IEnumerables can be an issue.  It has been enough of an issue that people are <a href="http://dotnet.sys-con.com/read/406638.htm">adding indexing for in-memory LINQ objects</a>, rather than simply iterating collections.</p>
<p>In earlier Visual Studio 2008 CTP&#8217;s, LINQ EntitySets implemented the iQueriable interface (directly?).  I&#8217;m not sure if at that point, this was implemented to elegantly generate SQL, I simply know that <a href="http://www.albahari.com/nutshell/">O&#8217;Reilly&#8217;s C# in a Nutshell</a> author Joseph Albahari made <a target="_blank" href="http://www.msdner.com/dev-archive/200/153-123-2008118.shtm">some</a> <a target="_blank" href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1968147&amp;SiteID=1">fuss</a> about the change. </p>
<p>It appears that Mr. Albahari is behind a library called <a href="http://www.albahari.com/nutshell/linqkit.html">LINQKit</a> designed to mitigate his qualms with the LINQ&#8217;s recently-neutered EntitySet classes.  While this library appears interesting, it critically doesn&#8217;t make EntitySets natively IQueriable.  Hence, I don&#8217;t see a way where LINQKit allows effortless, short syntax, efficient SQL queries to be built from existing database-derived classes.</p>
<p><strong></strong></p>
<p><strong>Winners:</strong> Tautologically, LINQ totally won this battle.</p>
<p><strong>Losers:</strong> LINQ EntitySets, for failing to combine short syntax and efficient SQL generation.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mapwrecker.wordpress.com/44/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mapwrecker.wordpress.com/44/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mapwrecker.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mapwrecker.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mapwrecker.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mapwrecker.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mapwrecker.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mapwrecker.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mapwrecker.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mapwrecker.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mapwrecker.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mapwrecker.wordpress.com/44/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mapwrecker.wordpress.com&blog=920496&post=44&subd=mapwrecker&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mapwrecker.wordpress.com/2007/12/19/linq-to-sql-vs-linq-to-objects/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>