<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Isaac @ MSDN : spatial</title><link>http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx</link><description>Tags: spatial</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Eye Candy of the Highest Order</title><link>http://blogs.msdn.com/isaac/archive/2008/06/02/eye-candy-of-the-highest-order.aspx</link><pubDate>Mon, 02 Jun 2008 12:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8563627</guid><dc:creator>isaac</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/isaac/comments/8563627.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=8563627</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=8563627</wfw:comment><description>&lt;p&gt;Hi Folks,&lt;/p&gt;  &lt;p&gt;One of the most common questions about the spatial support in SQL Server is how to visualize results.&amp;nbsp; To illustrate the problem, consider a query over zip code data:&lt;/p&gt;  &lt;div&gt;   &lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt; id, shapegeog&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt; zipcodes&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;where&lt;/span&gt; id &lt;span style="color: rgb(0, 0, 255);"&gt;like&lt;/span&gt; &lt;span style="color: rgb(0, 96, 128);"&gt;'981%'&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The results, while an accurate description of the data, are profoundly unhelpful:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_6.png" mce_href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_6.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_2.png" style="border-width: 0px;" alt="image" mce_src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_2.png" border="0" height="220" width="520"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;We can improve the human readability of this by fetching WKT instead of the original geography data:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_4.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_1.png" style="border-width: 0px;" alt="image" mce_src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_1.png" border="0" height="220" width="520"&gt;&lt;/a&gt;&amp;nbsp; &lt;/p&gt;

&lt;p&gt;While we can now read it, it still doesn't mean much.&amp;nbsp; Unlike social security numbers or names, visualization is almost required if you want to understand spatial data.&amp;nbsp; And if you really want to visualize the data, our only avenue has been to make use of an external program, such as Virtual Earth.&amp;nbsp; It's not super hard to make a mashup with VE, but it is another step.&lt;/p&gt;

&lt;p&gt;Thanks to some very hard work of a number of people, a very late feature has been slipped into the server: a map control.&amp;nbsp; With the map control, if you run the query, you get the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_8.png" mce_href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_8.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_3.png" style="border-width: 0px;" alt="image" mce_src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_3.png" border="0" height="254" width="520"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;And the magic reveals itself when you click that mysterious "Spatial result" tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_10.png" mce_href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_10.png"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_4.png" style="border-width: 0px;" alt="image" mce_src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/EyeCandyoftheHighestOrder_839F/image_thumb_4.png" border="0" height="381" width="786"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;These maps are interactive: you can zoom; you can pan; you can even label the results.&amp;nbsp; It isn't aimed at reporting, and this isn't a reusable component that can be used in other applications, but it can be invaluable in giving you a feel for what your results look like.&amp;nbsp; It goes far beyond eye candy: it actually allows you to understand your data.&lt;/p&gt;

&lt;p&gt;Unfortunately, it's a bit of a tease at the moment: the code just went in, which means none of this will be available in our upcoming RC0.&amp;nbsp; It will be in RTM, however, so you shouldn't have to wait too long.&lt;/p&gt;

&lt;p&gt;I can claim precious little credit for this, but if you're at TechEd this week, I'd be happy to demo it for you. So would Goldie Chaudhuri, who actually led the effort.&lt;/p&gt;

&lt;p&gt;Cheers, 
  &lt;br&gt;-Isaac&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8563627" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>Our Upcoming Builder API</title><link>http://blogs.msdn.com/isaac/archive/2008/05/30/our-upcoming-builder-api.aspx</link><pubDate>Fri, 30 May 2008 18:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8564843</guid><dc:creator>isaac</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/isaac/comments/8564843.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=8564843</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=8564843</wfw:comment><description>&lt;p&gt;Hi Folks,&lt;/p&gt;  &lt;p&gt;We have one more upcoming pre-release before we're done with SQL Server 2008, and while I've posted a &lt;a href="http://blogs.msdn.com/isaac/archive/2007/12/27/latitude-longitude-ordering.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2007/12/27/latitude-longitude-ordering.aspx"&gt;few&lt;/a&gt;&amp;nbsp;&lt;a href="http://blogs.msdn.com/isaac/archive/2008/01/03/mistakes-pay.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2008/01/03/mistakes-pay.aspx"&gt;articles&lt;/a&gt; &lt;a href="http://blogs.msdn.com/isaac/archive/2008/03/05/the-upcoming-geography-coordinate-order-swap-a-faq.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2008/03/05/the-upcoming-geography-coordinate-order-swap-a-faq.aspx"&gt;about&lt;/a&gt; the coordinate order swap, there's another exciting piece we're releasing: our builder API.&lt;/p&gt;  &lt;p&gt;Let's say you wanted to write a very simple method that shifted a geometry instance in space.&amp;nbsp; You could write this this today, but it would require writing code to digest one of the formats we support---WKT, WKB, or GML---perform the operation, and then recreate one of these data formats.&amp;nbsp; When the operation is so simple, the bulk of the effort needed will be in moving between formats.&lt;/p&gt;  &lt;p&gt;This seems pretty silly, given the fact that &lt;i&gt;we &lt;/i&gt;certainly have code that already digests these instances programmatically.&amp;nbsp; Why don't we give you access?&lt;/p&gt;  &lt;p&gt;Now we do.&lt;/p&gt;  &lt;p&gt;If you scroll down, you'll see a lot of C# code.&amp;nbsp; The solution we have can only be accessed directly through the CLR, but since the CLR is hosted in SQL Server, functionality developed can be deployed to the server and used through T-SQL.&amp;nbsp; This new functionality, which will be released in RC0, has three key parts:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;b&gt;IGeometrySink / IGeographySink interfaces.&lt;/b&gt;&amp;nbsp; These interfaces expose six methods---SetSRID, BeginGeometry, BeginFigure, AddLine, EndFigure, and EndGeometry---that can be called to describe a spatial instance with full fidelity.&amp;nbsp; Anyone can build a class that implements these methods, and pass an instance of their class to the...       &lt;br&gt;&lt;/li&gt;    &lt;li&gt;&lt;b&gt;...Populate() method on geography and geometry instances&lt;/b&gt;.&amp;nbsp; This method takes an IGeometrySink or IGeographySink instance and makes the appropriate calls to exactly describe the instance.&amp;nbsp; If, e.g., you wanted to build code to create KML from geography instances, you'd build a KML translator that implemented IGeographySink, and call Populate() with it.&amp;nbsp; If you wanted to write the shift example, you'd still have the problem of creating the result instance, and this is handled by...       &lt;br&gt;&lt;/li&gt;    &lt;li&gt;&lt;b&gt;...Builder classes for geometry and geography.&lt;/b&gt;&amp;nbsp; SqlGeometryBuilder and SqlGeographyBuilder implement their respective sink interfaces, and expose an additional property: ConstructedGeometry.&amp;nbsp; After a series of calls to the interface that create a complete instance, a geometry or geography instance will be available in the property.&amp;nbsp; Because the interfaces are the same for both digesting and creating spatial instances, it is very easy to pipeline input and output operations. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So, let's take a look at a working example that solves our shifting problem.&amp;nbsp; The main part is to write our own implementation of IGeometrySink that will perform the shifting.&amp;nbsp; Our constructor will take the amount of shift we want in the x and y directions, as well as a target IGeometrySink instance.&amp;nbsp; The implementations of each of the IGeometrySink methods will simply pass the calls through to the target, except that every point passed through will be shifted first.&lt;/p&gt;  &lt;div&gt;   &lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;using&lt;/span&gt; Microsoft.SqlServer.Types;&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;namespace&lt;/span&gt; Tools&lt;br&gt;{&lt;br&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; GeometryShifter : IGeometrySink&lt;br&gt;    {&lt;br&gt;        IGeometrySink _target;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; _xShift;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; _yShift;&lt;br&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; GeometryShifter(&lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; xShift, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; yShift, IGeometrySink target)&lt;br&gt;        {&lt;br&gt;            _target = target;&lt;br&gt;            _xShift = xShift;&lt;br&gt;            _yShift = yShift;&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 128, 0);"&gt;// Each AddLine call will just move the endpoint by the required amount.&lt;/span&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; AddLine(&lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; x, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; y, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt;? z, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt;? m)&lt;br&gt;        {&lt;br&gt;            _target.AddLine(x + _xShift, y + _yShift, z, m);&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 128, 0);"&gt;// Each BeginFigure call will just move the start point by the required amount.&lt;/span&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; BeginFigure(&lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; x, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; y, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt;? z, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt;? m)&lt;br&gt;        {&lt;br&gt;            _target.BeginFigure(x + _xShift, y + _yShift, z, m);&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 128, 0);"&gt;// Just pass through without change.&lt;/span&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; BeginGeometry(OpenGisGeometryType type)&lt;br&gt;        {&lt;br&gt;            _target.BeginGeometry(type);&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 128, 0);"&gt;// Just pass through without change.&lt;/span&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; EndFigure()&lt;br&gt;        {&lt;br&gt;            _target.EndFigure();&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 128, 0);"&gt;// Just pass through without change.&lt;/span&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; EndGeometry()&lt;br&gt;        {&lt;br&gt;            _target.EndGeometry();&lt;br&gt;        }&lt;br&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 128, 0);"&gt;// Just pass through without change.&lt;/span&gt;&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; SetSrid(&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; srid)&lt;br&gt;        {&lt;br&gt;            _target.SetSrid(srid);&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To use this in SQL Server, we need to wrap it in a function that can be registered and used in the server.&amp;nbsp; To do this, we create a function that puts the pipeline together and runs it.&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;using&lt;/span&gt; Microsoft.SqlServer.Types;&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;namespace&lt;/span&gt; Tools&lt;br&gt;{&lt;br&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;partial&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; Functions&lt;br&gt;    {&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; SqlGeometry ShiftGeometry(SqlGeometry g, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; xShift, &lt;span style="color: rgb(0, 0, 255);"&gt;double&lt;/span&gt; yShift)&lt;br&gt;        {&lt;br&gt;            SqlGeometryBuilder constructed = &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; SqlGeometryBuilder();&lt;br&gt;            GeometryShifter shifter = &lt;span style="color: rgb(0, 0, 255);"&gt;new&lt;/span&gt; GeometryShifter(xShift, yShift, constructed);&lt;br&gt;            g.Populate(shifter);&lt;br&gt;            &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt; constructed.ConstructedGeometry;&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Because of SQL Server's CLR support, we can build this to Tools.dll and load it into the server.&amp;nbsp; After that, we can register the function and use it directly from T-SQL:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;create&lt;/span&gt; assembly Tools &lt;span style="color: rgb(0, 0, 255);"&gt;from&lt;/span&gt; &lt;span style="color: rgb(0, 96, 128);"&gt;'c:\tmp\Tools.dll'&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;go&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;create&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;function&lt;/span&gt; ShiftGeometry(@g geometry, @x &lt;span style="color: rgb(0, 0, 255);"&gt;float&lt;/span&gt;, @y &lt;span style="color: rgb(0, 0, 255);"&gt;float&lt;/span&gt;)&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;returns&lt;/span&gt; geometry&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;external&lt;/span&gt; name Tools.[Tools.Functions].ShiftGeometry&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;go&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;declare&lt;/span&gt; @g geometry = &lt;span style="color: rgb(0, 96, 128);"&gt;'LINESTRING (0 0, 1 1, 12 3, 4 0)'&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt; @g.ToString()&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;union&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;all&lt;/span&gt;&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;select&lt;/span&gt; dbo.ShiftGeometry(@g, 10, 10).ToString()&lt;br&gt;go&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This yields:&lt;/p&gt;

&lt;div&gt;
  &lt;pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: rgb(244, 244, 244);"&gt;LINESTRING (0 0, 1 1, 12 3, 4 0)&lt;br&gt;LINESTRING (10 10, 11 11, 22 13, 14 10)&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is a pretty simple example, but it illustrates the power of the approach.&amp;nbsp; Now you can build functions like this without all of the parsing glue.&lt;/p&gt;

&lt;p&gt;Our spatial implementation makes use of this kind of API internally, and it was this internal use that inspired us to release it to users of the system as well.&amp;nbsp; We see &lt;i&gt;many &lt;/i&gt;cases in which new spatial operations can be added to the server through this API, and we hope that you can find some as well.&amp;nbsp; (Looking at the &lt;a href="http://forums.microsoft.com/msdn/showforum.aspx?forumid=1629&amp;amp;siteid=1&amp;amp;sb=0&amp;amp;d=1&amp;amp;at=7&amp;amp;ft=11&amp;amp;tf=0&amp;amp;pageid=0" mce_href="http://forums.microsoft.com/msdn/showforum.aspx?forumid=1629&amp;amp;siteid=1&amp;amp;sb=0&amp;amp;d=1&amp;amp;at=7&amp;amp;ft=11&amp;amp;tf=0&amp;amp;pageid=0"&gt;Spatial forum&lt;/a&gt;, we can find &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2496843&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2496843&amp;amp;SiteID=1"&gt;many&lt;/a&gt; &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3339889&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3339889&amp;amp;SiteID=1"&gt;examples&lt;/a&gt; &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2302332&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2302332&amp;amp;SiteID=1"&gt;of&lt;/a&gt; &lt;a href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3135630&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3135630&amp;amp;SiteID=1"&gt;problems&lt;/a&gt; &lt;a href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3006381&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3006381&amp;amp;SiteID=1"&gt;that&lt;/a&gt; &lt;a href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=2947967&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=2947967&amp;amp;SiteID=1"&gt;can&lt;/a&gt; &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2892313&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2892313&amp;amp;SiteID=1"&gt;be&lt;/a&gt; &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2657628&amp;amp;SiteID=1" mce_href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2657628&amp;amp;SiteID=1"&gt;tackled&lt;/a&gt; with this approach, and this list is nowhere near exhaustive.)&lt;/p&gt;

&lt;p&gt;Cheers, 
  &lt;br&gt;-Isaac&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8564843" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>Where are my Spatial Columns?</title><link>http://blogs.msdn.com/isaac/archive/2008/04/15/where-are-my-spatial-columns.aspx</link><pubDate>Tue, 15 Apr 2008 23:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8398197</guid><dc:creator>isaac</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/isaac/comments/8398197.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=8398197</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=8398197</wfw:comment><description>&lt;DIV&gt;
&lt;P&gt;Hi Folks,&lt;/P&gt;
&lt;P&gt;I've been asked a few times how to find out what spatial columns are defined in a database.&amp;nbsp; We don't have any special table for this, but you can easily find out by looking at the usual system views:&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;SELECT&lt;/SPAN&gt; ta.name &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; table_name, co.name &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; column_name&lt;BR&gt;&lt;SPAN class=kwrd&gt;FROM&lt;/SPAN&gt; sys.tables ta &lt;SPAN class=kwrd&gt;JOIN&lt;/SPAN&gt; sys.columns co&lt;BR&gt;      &lt;SPAN class=kwrd&gt;ON&lt;/SPAN&gt; ta.object_id = co.object_id&lt;BR&gt;&lt;SPAN class=kwrd&gt;JOIN&lt;/SPAN&gt; sys.types ty&lt;BR&gt;      &lt;SPAN class=kwrd&gt;ON&lt;/SPAN&gt; co.user_type_id = ty.user_type_id&lt;BR&gt;&lt;SPAN class=kwrd&gt;WHERE&lt;/SPAN&gt; ty.name = &lt;SPAN class=str&gt;'geography'&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;OR&lt;/SPAN&gt; ty.name = &lt;SPAN class=str&gt;&lt;FONT color=red&gt;'geometry'&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;There's nothing special about spatial here: you can replace the type names in the WHERE clause of the query with any other type you'd like to find as well.&amp;nbsp; For example, a simple change finds all integer columns:&lt;/P&gt;
&lt;DIV&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;SELECT&lt;/SPAN&gt; ta.name &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; table_name, co.name &lt;SPAN class=kwrd&gt;as&lt;/SPAN&gt; column_name&lt;BR&gt;&lt;SPAN class=kwrd&gt;FROM&lt;/SPAN&gt; sys.tables ta &lt;SPAN class=kwrd&gt;JOIN&lt;/SPAN&gt; sys.columns co&lt;BR&gt;      &lt;SPAN class=kwrd&gt;ON&lt;/SPAN&gt; ta.object_id = co.object_id&lt;BR&gt;&lt;SPAN class=kwrd&gt;JOIN&lt;/SPAN&gt; sys.types ty&lt;BR&gt;      &lt;SPAN class=kwrd&gt;ON&lt;/SPAN&gt; co.user_type_id = ty.user_type_id&lt;BR&gt;&lt;SPAN class=kwrd&gt;WHERE&lt;/SPAN&gt; ty.name = &lt;SPAN class=str&gt;'int'&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;Cheers, &lt;BR&gt;-Isaac&lt;/P&gt;
&lt;P&gt;[16 April 2008]:&amp;nbsp;Updated to correct a typo in the first query.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8398197" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/t-sql/default.aspx">t-sql</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>More on the Multi-Level Grid</title><link>http://blogs.msdn.com/isaac/archive/2008/04/08/more-on-the-multi-level-grid.aspx</link><pubDate>Tue, 08 Apr 2008 19:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8369313</guid><dc:creator>isaac</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/isaac/comments/8369313.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=8369313</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=8369313</wfw:comment><description>&lt;P&gt;Hi Folks,&lt;/P&gt;
&lt;P&gt;In my &lt;A href="http://blogs.msdn.com/isaac/archive/2008/03/01/basic-multi-level-grids.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2008/03/01/basic-multi-level-grids.aspx"&gt;last indexing post&lt;/A&gt;, I filled in most of the details about our multi-level grid index.&amp;nbsp; Let me clean up a few lingering questions about our planar grid. We'll do this Q&amp;amp;A style:&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Q:&lt;/B&gt; &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;I&gt;What happens if I set the maximum number of cells-per-object so small that I cannot obtain a covering of my object?&lt;/I&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;A: &lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;To make this concrete, let's take a look at one of the pictures from last time:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/MoreontheMultiLevelGrid_85A2/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/MoreontheMultiLevelGrid_85A2/image_2.png"&gt;&lt;IMG style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=240 alt=image src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/MoreontheMultiLevelGrid_85A2/image_thumb.png" width=240 border=0 mce_src="http://blogs.msdn.com/blogfiles/isaac/WindowsLiveWriter/MoreontheMultiLevelGrid_85A2/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;In this schematic, there are four top-level cells, and we can see that we need at least three cells to tile the object.&amp;nbsp; In this picture, we are using 13 cells, so we've set the maximum number of cells-per-object to at least that.&amp;nbsp; But what if we set it to two?&lt;/P&gt;
&lt;P&gt;The answer is that in the case where the number of first-level cells needed to tile the object exceeds the max cells-per-object, we violate cells-per-object constraint.&amp;nbsp; This is really the only situation in which we'll do that, but it's necessary in order to ensure that we tile the object, and this is required in order to guarantee correct query results.&lt;/P&gt;
&lt;P&gt;Keep in mind that in a real index, the number of top level cells is either 16, 64, or 256, and this will only happen if the max cells-per-object exceeds that value.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;Q:&lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;I&gt;What if I have an object that falls outside, or partially outside the bounding box I have defined?&amp;nbsp; Will I miss results?&lt;/I&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;A:&lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;There is an implicit extra cell in the tessellation, what we call the &lt;I&gt;root cell&lt;/I&gt;.&amp;nbsp; The root cell covers everything outside of the bounding box you've defined, and will be used to cover any object that touches it.&amp;nbsp; We can use this to guarantee correct results even if your object isn't well contained by your bounding box.&amp;nbsp; What will suffer is performance, and so it is still important to get the bounding box correct.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;Q:&lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;I&gt;Are there times where you can answer the query using solely the index?&lt;/I&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;A:&lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Yes.&amp;nbsp; Consider a cell that is touched by one object, and &lt;I&gt;completely covered&lt;/I&gt; by another.&amp;nbsp; We can tell that these two objects must intersect based solely on this fact: there is no need to actually run the intersection predicate.&amp;nbsp; We call this "intermediate filtering" (not the best name, but we needed something to call it) and we do implement it.&amp;nbsp; To do this, we store whether the object touches or covers the cell in the index row.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;Q:&lt;/B&gt; &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;I&gt;Which predicates are supported on an index?&lt;/I&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;A:&lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;It depends on the type.&amp;nbsp; For geometry, we support STIntersects, STEquals, STOverlaps, STTouches, STWithin, STContains, STDistance, and STFilter.&amp;nbsp; On geography we only support STIntersects, STEquals, STDistance, and Filter.&amp;nbsp; We don't support the others simply because they don't exist on the type.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;Q:&lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;I&gt;What is the difference between STIntersects and Filter?&lt;/I&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;B&gt;A:&lt;/B&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;If there isn't an index, they do exactly the same thing.&amp;nbsp; This can happen on the client, or on the server if you haven't defined an index (or if the index isn't chosen for some reason).&amp;nbsp; When there is an index involved, Filter will &lt;I&gt;not &lt;/I&gt;do any secondary filtering.&amp;nbsp; I.e., it is only guaranteed to return a superset of the results an STIntersects predicate will return: it may return extras.&lt;/P&gt;
&lt;P&gt;This is useful for applications that are simply displaying results, are not sensitive to some extras, and want to avoid the cost of the secondary filter.&amp;nbsp; If you need precise results, use STIntersects.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;If there are more questions, please ask, and I'll answer them here.&amp;nbsp; So far we've only talked about geometry, so next time I'll either fill in the gaps around geography or answer more questions.&lt;/P&gt;
&lt;P&gt;Cheers, &lt;BR&gt;-Isaac&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8369313" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>The Unexpected Too-Large Polygon</title><link>http://blogs.msdn.com/isaac/archive/2008/04/06/the-unexpected-too-large-polygon.aspx</link><pubDate>Sun, 06 Apr 2008 03:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8361857</guid><dc:creator>isaac</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/isaac/comments/8361857.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=8361857</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=8361857</wfw:comment><description>&lt;P&gt;Hi Folks,&lt;/P&gt;
&lt;P&gt;I recently got contacted via email with the following problem:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;...&lt;/P&gt;
&lt;P&gt;I have 2 complex polygons, representing district boundaries.&amp;nbsp; The polygons look correct, but I'm getting exceptions when I try to create the type. &lt;BR&gt;&lt;BR&gt;I've attached the wkt polygons to the email. &lt;BR&gt;&lt;BR&gt;These polygons are stored in a table, but I've tried it without the table and get the same result. &lt;BR&gt;&lt;BR&gt;Here's the sql I'm trying to execute: &lt;BR&gt;&lt;BR&gt;declare @g geography; &lt;BR&gt;set @g = geography::STPolyFromText(@wkt, 4268) &lt;BR&gt;select @g.ToString() &lt;BR&gt;&lt;BR&gt;where @wkt is replaced by the correct polygon string.&lt;/P&gt;
&lt;P&gt;...&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now, I should point out that this is a very nice error report.&amp;nbsp; They've told me what their data is, they included their data, and they told me very clearly what they're trying to do.&amp;nbsp; (Perhaps knowing what version they're using would good, but I'm getting picky.)&lt;/P&gt;
&lt;P&gt;But here's the kicker that saved me any debugging:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;... &lt;BR&gt;Here is the error message I receive: &lt;BR&gt;&lt;BR&gt;A .NET Framework error occurred during execution of user defined routine or aggregate 'geography': &lt;BR&gt;Microsoft.SqlServer.Types.GLArgumentException: 24205: The specified input does not represent a valid geography instance because it exceeds a single hemisphere. Each geography instance must fit inside a single hemisphere. A common reason for this error is that a polygon has the wrong ring orientation. &lt;BR&gt;Microsoft.SqlServer.Types.GLArgumentException: &lt;BR&gt;&amp;nbsp;&amp;nbsp; at Microsoft.SqlServer.Types.GLNativeMethods.ThrowExceptionForHr(GL_HResult errorCode) &lt;BR&gt;&amp;nbsp;&amp;nbsp; at Microsoft.SqlServer.Types.GLNativeMethods.GeodeticIsValid(GeometryData g) &lt;BR&gt;&amp;nbsp;&amp;nbsp; at Microsoft.SqlServer.Types.SqlGeography.IsValidExpensive() &lt;BR&gt;&amp;nbsp;&amp;nbsp; at Microsoft.SqlServer.Types.SqlGeography.ConstructGeographyFromUserInput(GeometryData g, Int32 srid) &lt;BR&gt;&amp;nbsp;&amp;nbsp; at Microsoft.SqlServer.Types.SqlGeography.STPolyFromText(SqlChars polygonTaggedText, Int32 srid) &lt;BR&gt;&lt;BR&gt;I looked at all the nodes, and they are all in the same hemisphere, so I'm a little confused with what might be going on. &lt;BR&gt;...&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So, what's going on?&amp;nbsp; Ring ordering. &lt;/P&gt;
&lt;P&gt;I've &lt;A href="http://blogs.msdn.com/isaac/archive/2007/10/29/geography-and-ring-orientation.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2007/10/29/geography-and-ring-orientation.aspx"&gt;posted on this before&lt;/A&gt;, but let's recap.&amp;nbsp; On a round Earth, defining a polygon by a ring is ambiguous.&amp;nbsp; Consider the polygon defined by a ring around the equator: does this describe the northern or southern hemisphere?&amp;nbsp; A small ring could describe either, say, a small island in a large ocean, or the large ocean itself.&lt;/P&gt;
&lt;P&gt;To get out of this pickle, we disambiguate with a standard trick: we take ring orientation into account.&amp;nbsp; We simply define the left side of the ring as it is drawn to be inside the polygon.&lt;/P&gt;
&lt;P&gt;If we put this together with our current (unfortunate) limitation that we do not deal with objects that exceed a hemisphere, and it becomes clear what's going on.&amp;nbsp; While the polygon looks like it's nice and small, the rings are inverted, and so it's actually quite large.&amp;nbsp; We can't handle it: cue the exception.&lt;/P&gt;
&lt;P&gt;I describe this hemisphere limitation as unfortunate, and it remains one of the biggest items the spatial team would like to fix up, but in this case it has actually helped catch an error.&lt;/P&gt;
&lt;P&gt;I'll talk a bit more about our hemisphere limitation in a future post.&amp;nbsp; It's not quite as simple as we let on.&lt;/P&gt;
&lt;P&gt;Cheers, &lt;BR&gt;-Isaac&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8361857" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>February CTP Optimizer Issue</title><link>http://blogs.msdn.com/isaac/archive/2008/03/11/february-ctp-optimizer-issue.aspx</link><pubDate>Tue, 11 Mar 2008 06:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8143705</guid><dc:creator>isaac</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/isaac/comments/8143705.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=8143705</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=8143705</wfw:comment><description>&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Hi Folks,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;We don't call them betas, but that's basically what CTPs are: they let us suss out problems before we drop a final product on everyone.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well, we've found a regression in the February CTP spatial support that we'd like to let you know about.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Essentially, a costing problem was introduced that leads us to choose poor plans for spatial queries.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This seems to usually manifest itself by choosing merge joins instead of loop joins between the spatial index and the base table, and that generally doesn't work too well.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Why is a merge join such a bad plan in this case?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you've been following my indexing posts, you'll understand that we generally end up with a small number of rows that pass our primary filter (our index).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We have to then join those back to the base table to pull out the spatial object to which the index row refers.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;This is usually best done through a loop join that runs over each index row and &lt;SPAN style="FONT-STYLE: italic"&gt;seeks&lt;/SPAN&gt; into the base table for each of the objects.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;However, if a merge join is chosen, then we risk &lt;SPAN style="FONT-STYLE: italic"&gt;scanning &lt;/SPAN&gt;the entire base table to feed into our merge.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is usually not a wise choice.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;What can you do about this if you're running the February CTP?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A good general fix is to force loop joins in your query.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Perhaps the simplest way to do this is by adding an "OPTION (LOOP JOIN)" to the end of your query.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;On the positive side, this has already been fixed, so you should see better plans in our next public release.&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Cheers,&lt;/P&gt;
&lt;P style="FONT-SIZE: 11pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;-Isaac&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8143705" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>The Upcoming Geography Coordinate Order Swap---A FAQ</title><link>http://blogs.msdn.com/isaac/archive/2008/03/05/the-upcoming-geography-coordinate-order-swap-a-faq.aspx</link><pubDate>Wed, 05 Mar 2008 20:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8053398</guid><dc:creator>isaac</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/isaac/comments/8053398.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=8053398</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=8053398</wfw:comment><description>&lt;P&gt;Hi Folks,&lt;/P&gt;
&lt;P&gt;I just thought I'd take a few moments clarify the upcoming &lt;A class="" href="http://blogs.msdn.com/isaac/archive/2007/12/27/latitude-longitude-ordering.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2007/12/27/latitude-longitude-ordering.aspx"&gt;coordinate order swap&lt;/A&gt; for the geography type.&amp;nbsp; Here's a quick FAQ on the issue:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;What exactly is the change?&lt;BR&gt;&lt;BR&gt;We are&amp;nbsp;swapping the coordinate order for well-known text (WKT) and well-known binary (WKB) formats from latitude-longitude to longitude-latitude.&amp;nbsp;&amp;nbsp;E.g.,&amp;nbsp;a point in the Seattle area might be represented in WKT as "POINT(44 -122)" in the current ordering; in the new order&amp;nbsp;it will be "POINT(-122 44)".&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Why are we making this change?&lt;BR&gt;&lt;BR&gt;Because of customer feedback.&amp;nbsp; While&amp;nbsp;common practice&amp;nbsp;almost universally uses latitude-longitude ordering, the de facto standard&amp;nbsp;for WKT and WKB is to use a longitude-latitude order.&amp;nbsp;&amp;nbsp;Making this change will make it much easier for&amp;nbsp;customers to load WKT and WKB data into the geography type.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;What about GML?&amp;nbsp;&lt;BR&gt;&lt;BR&gt;The standard paractice for GML is to use latitude-longitude ordering, and so no change will be made for GML.&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Is the on-disk format changing?&lt;BR&gt;&lt;BR&gt;Nope.&amp;nbsp; Ths is just a matter of changing our routines that import and export data.&amp;nbsp; Nothing beyond those routines will change.&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;What about geometry?&lt;BR&gt;&lt;BR&gt;There is no change to the geometry type.&amp;nbsp; Geometry deals with objects on the plane, and is pretty agnostic about the coordinate order outsidfe of the STX and STY properties.&lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;When is the swap happening?&lt;BR&gt;&lt;BR&gt;It is not the current Februrary CTP, but the team is working on it now.&amp;nbsp; Expect to see it in our next public release.&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;If there are more questions, I'll be happy to answer them here.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;BR&gt;-Isaac&lt;/P&gt;
&lt;P mce_keep="true"&gt;Minor&amp;nbsp;Update:&amp;nbsp;I originally got the WKT examples at the top wrong, placing commas between coordinates.&amp;nbsp; The examples have been updated to their correct, comma-free state.&amp;nbsp; (Thanks, Steven!)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8053398" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>Basic Multi-Level Grids</title><link>http://blogs.msdn.com/isaac/archive/2008/03/01/basic-multi-level-grids.aspx</link><pubDate>Sat, 01 Mar 2008 05:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7968742</guid><dc:creator>isaac</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/isaac/comments/7968742.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=7968742</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=7968742</wfw:comment><description>&lt;P&gt;Hi Folks,&lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://blogs.msdn.com/isaac/archive/2008/02/05/picking-up-on-indexing-moving-beyond-the-simple-grid.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2008/02/05/picking-up-on-indexing-moving-beyond-the-simple-grid.aspx"&gt;Last time&lt;/A&gt;, we highlighted several problems with a simple grid index.&amp;nbsp; If you don't recall---and since it's been a while, that wouldn't be a surprise---you may want to review them.&amp;nbsp; In this post I'll start to describe how we get around them.&lt;/P&gt;
&lt;P&gt;In SQL Server, we don't use a simple grid like the one described.&amp;nbsp; Instead, we use a multi-level grid, which ends up looking very much like a quad tree.&amp;nbsp; Basically, instead of having one grid level, we have four, with each lower-level grid nested in the one above.&lt;/P&gt;
&lt;P&gt;Let's look at an example.&amp;nbsp; If we have a 2x2 grid at each level, then we can tile the object below with three tiles at the top-level grid:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH: 330px; HEIGHT: 330px" height=330 src="http://blogs.msdn.com/photos/isaac/images/7968868/original.aspx" width=330 mce_src="http://blogs.msdn.com/photos/isaac/images/7968868/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;These tiles cover the object, which is a property we want to maintain for our indexing scheme, but there's a lot of extra coverage.&amp;nbsp; This extra means we're likely to have a good number of false positives from our primary filter.&amp;nbsp; We can go to a second-level gridding instead:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 330px; HEIGHT: 330px" height=330 src="http://blogs.msdn.com/photos/isaac/images/7968975/original.aspx" width=330 mce_src="http://blogs.msdn.com/photos/isaac/images/7968975/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;At this level, we've trimmed some of the extra slop from the edges, but our description of the object has become more complex as well.&amp;nbsp;&amp;nbsp;With our four levels, we can push this even further---here's what a fourth-level tiling of the object would look like:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 330px; HEIGHT: 330px" height=330 src="http://blogs.msdn.com/photos/isaac/images/7968875/original.aspx" width=330 mce_src="http://blogs.msdn.com/photos/isaac/images/7968875/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;This description is nice and tight---there's very extra covering of the object---but it's also very complicated.&amp;nbsp; What's key to&amp;nbsp;keeping the complexity down is that&amp;nbsp;we don't require that all object use the same level tiling, nor do we require that all tiles for a particular object all be at the same level.&amp;nbsp; We can mix as we wish.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The ability to mix levels in our tiling leads us to two optimizations.&amp;nbsp; The first, which is always used, is that if we find that all subtiles of a particular tile are touched by the object, then we won't further subdivide the cell.&amp;nbsp; Subdividing gives us nothing but more cells.&amp;nbsp; Perhaps this is clearer visually; below is a picture of the same tiling above with this optimization applied:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 330px; HEIGHT: 330px" height=330 src="http://blogs.msdn.com/photos/isaac/images/7968877/original.aspx" width=330 mce_src="http://blogs.msdn.com/photos/isaac/images/7968877/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;As you can see, this greatly reduces the number of tiles we have, and does so by mixing levels.&amp;nbsp; A second way to reduce tiles is through an explicit limit.&amp;nbsp; We default this limit to 16, but the user can tweak it to their liking.&amp;nbsp; When we decompose an object, we do a breath-first walk down the tree decomposing tiles, and we stop when we hit the pre-defined limit.&amp;nbsp; E.g., we might end up with:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 330px; HEIGHT: 330px" height=330 src="http://blogs.msdn.com/photos/isaac/images/7968888/original.aspx" width=330 mce_src="http://blogs.msdn.com/photos/isaac/images/7968888/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;There's much more to say about this, but before I leave it for now, let me point out that&amp;nbsp;while these examples use 2x2 decompositions at each level, we&amp;nbsp;use more.&amp;nbsp; The exact amount is, in fact, adjustable: the user can set each level to low (4x4) medium (8x8) or high&amp;nbsp;(16x16).&lt;/P&gt;
&lt;P mce_keep="true"&gt;How should the user tweak these various parameters?&amp;nbsp; It's hard to give general advice, as it's a very data- and query-dependent calculation, but we feel that we have picked some defaults that will work well for most people.&amp;nbsp; We may have better advice as more people start using the index and we get reports on what worked for them.&amp;nbsp; (Yes, we're begging you to send us your findings!)&lt;/P&gt;
&lt;P mce_keep="true"&gt;Next&amp;nbsp;time we'll continue with some more details about the mult-level grid.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;BR&gt;-Isaac&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7968742" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial+indexing/default.aspx">spatial indexing</category></item><item><title>One Type, Two Types...</title><link>http://blogs.msdn.com/isaac/archive/2007/05/29/one-type-two-types.aspx</link><pubDate>Tue, 29 May 2007 17:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2969351</guid><dc:creator>isaac</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/isaac/comments/2969351.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=2969351</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=2969351</wfw:comment><description>&lt;P&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Calibri"&gt;This is a little bit less of an introductory post than the &lt;/SPAN&gt;&lt;A href="http://blogs.msdn.com/isaac/archive/2007/05/16/sql-server-spatial-support-an-introduction.aspx" mce_href="http://blogs.msdn.com/isaac/archive/2007/05/16/sql-server-spatial-support-an-introduction.aspx"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Calibri"&gt;last one&lt;/SPAN&gt;&lt;/A&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Calibri"&gt;, but there was quite a bit of discussion about our decision to split our spatial types in two---one for our planar ("flat-Earth") model and one for our ellipsoidal ("round-Earth") model---so I thought I'd address it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To be honest, this is something that we struggled with, but in the end we favored the two-type model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Here's a quick look at of some of our reasoning.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;Let me begin with a roughly analogous situation: SQL Server's floating- and fixed-point types, float and decimal.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;These types really have the same interface, so we could have conceivably had one type with a floating-point/fixed-point option.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Why choose two types over one?&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;One reason is that mingling the two would be confusing, since their semantics differ.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we didn't separate the types, then we could write a method that took that single numeric type as input.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If we performed any operations that depended on the difference in semantics, then we would have to be careful to check which one we were dealing with and proceed accordingly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We could skip these checks if we always expected, say, fixed-point, but we could be almost certain that if our code survived long enough, some schmuck would eventually hand us a floating-point value.&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;By separating the types, there is a clear division, and given an instance of a particular type we know exactly what we're dealing with.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Additionally, we know that nobody could hand us the wrong type later on.&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;So by separating the types we've made things more explicit and clear, but one can argue that since the semantics are often the same---or at least close enough that we don't care---we could save code by unifying the types.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is undoubtedly true: there's a tradeoff to be made.&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;We face a similar problem with spatial types.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The two types often behave quite similarly, but there are some key differences.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The tradeoff is the same: you can save code by unifying the types at the expense of clarity and robustness.&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;So, what's different between the planar and ellipsoidal&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;types?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well, beyond the obvious---one is flat, one is round---here are some examples:&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in 0in 0in 0.375in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; LIST-STYLE-TYPE: disc"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Calibri"&gt;In the planar system, distances and areas are given in the same unit of measure as coordinates.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;E.g., the distance between (2, 2) and (5, 6) is 5 units, regardless of what units are.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a geodetic system, coordinates are given in degrees, but it hardly makes sense to give lengths and areas in degrees or square degrees---we'd much prefer something like meters.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; LIST-STYLE-TYPE: disc"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Calibri"&gt;In the planar system, we don't care about the orientation of a polygon.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;E.g., a polygon described by ((0, 0), (10, 0), (0, 20), (0, 0)) is the same as one described by ((0, 0), (0, 20), (10, 0), (0, 0)).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The OGC Simple Features for SQL specification doesn't dictate a ring ordering, so we don't enforce one.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In a geodetic system, a polygon is ambiguous without an orientation.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;E.g., which hemisphere would a ring around the equator describe?&lt;/SPAN&gt;&lt;/LI&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; LIST-STYLE-TYPE: disc"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Calibri"&gt;In planar coordinates, it makes sense to use a bounding box as a cheap substitute for an object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In geodetic coordinates, a bounding circle is more natural.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; LIST-STYLE-TYPE: disc"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: Calibri"&gt;OGC talks about outer rings and inner rings, but this distinction makes little sense for a geodetic type: any ring of a polygon can be taken to be the outer one.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Of course, this is only a start.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In addition, we are aiming to simplify things a little bit in our round-Earth type.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We thought that given all of this, merging the two types would be confusing, especially for the non-experts out there, so we decided to separate things into two types.&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Is that the right decision?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We think so, but we recognize that not everyone may agree with us.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We look forward to hearing from you.&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;Cheers,&lt;/P&gt;
&lt;P style="FONT-SIZE: 12pt; MARGIN: 0in; FONT-FAMILY: Calibri"&gt;-Isaac&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2969351" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item><item><title>SQL Server Spatial Support: An Introduction</title><link>http://blogs.msdn.com/isaac/archive/2007/05/16/sql-server-spatial-support-an-introduction.aspx</link><pubDate>Thu, 17 May 2007 01:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2681837</guid><dc:creator>isaac</dc:creator><slash:comments>32</slash:comments><comments>http://blogs.msdn.com/isaac/comments/2681837.aspx</comments><wfw:commentRss>http://blogs.msdn.com/isaac/commentrss.aspx?PostID=2681837</wfw:commentRss><wfw:comment>http://blogs.msdn.com/isaac/rsscomments.aspx?PostID=2681837</wfw:comment><description>&lt;FONT face=Calibri&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT size=3&gt;I’ve been pretty quiet around here, and at least part of the reason is that we’ve been pretty tight-lipped about what we’ve been up to.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ve now gone public—we’re providing support for geospatial data in our next version of SQL Server, codenamed Katmai.&amp;nbsp; The Virtual Earth folks &lt;A class="" href="http://virtualearth.spaces.live.com/blog/cns!2BBC66E99FDCDB98!8675.entry#comment" mce_href="http://virtualearth.spaces.live.com/blog/cns!2BBC66E99FDCDB98!8675.entry#comment"&gt;mentioned this in their blog&lt;/A&gt;&amp;nbsp;(&lt;A class="" href="http://www.spatiallyadjusted.com/2007/05/10/microsoft-sql-server-2008-to-have-spatial-data-natively/" mce_href="http://www.spatiallyadjusted.com/2007/05/10/microsoft-sql-server-2008-to-have-spatial-data-natively/"&gt;others&lt;/A&gt;, &lt;A class="" href="http://www.directionsmag.com/article.php?article_id=2459&amp;amp;trv=1" mce_href="http://www.directionsmag.com/article.php?article_id=2459&amp;amp;trv=1"&gt;too&lt;/A&gt;)&amp;nbsp;but&amp;nbsp;now&amp;nbsp;I can make a little more noise.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT size=3&gt;What I’d like to do first is try to explain to the folks out there who aren’t experts in the field what this all means and give a very high-level tour of what we’re providing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT size=3&gt;First, what is geospatial data?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For starters, we mean locations on the Earth.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s more than location, though: we mean the location and shape of objects on the Earth.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Think of the description of roads, states, lakes, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, think of something like Live Maps:&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;&lt;IMG title="Microsoft's Main Campus" style="WIDTH: 491px; HEIGHT: 474px" height=474 alt="Microsoft's Main Campus" src="http://blogs.msdn.com/photos/isaac/images/2681687/original.aspx" width=491 mce_src="http://blogs.msdn.com/photos/isaac/images/2681687/original.aspx"&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;In addition to the normal objects, I’ve added a polygon that shows Microsoft’s main campus.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We want to be able to store all of the data on this map—the roads, the parks, and user-generated polygon—in SQL Server.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Being a database, we want to be able to ask questions about the data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, “What are the roads that intersect Microsoft’s main campus?”&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A more complex example would be “What is the area of all parks within 1 kilometer of Microsoft’s main campus?”&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;How do we do this?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;First, we need new data types to be able to store this information.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Toward this end, we are introducing two new types in Katmai:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri size=3&gt;The first type, “geography”, will store points, lines, polygons, and collections of these in latitude/longitude coordinates using a round-Earth model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Most commonly-available data is given in latitude/longitude coordinates, so we expect that most people will want to use this type.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Furthermore, this type will give correct computations on a true ellipsoidal model of the planet.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What is the area of Indonesia?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Will my flight from Seattle to Beijing take me over North Korea?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Where can I store my GPS readings?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is the type for you.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri size=3&gt;A “geometry” type to support flat-earth data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For those of you who are familiar with such things, this type is our OGC-compliant offering.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In some ways, this is a more specialty offering for people who need to work in projected map coordinates either for legacy or legal reasons, but this type can be used for things like interior spaces as well, e.g., “Where in this warehouse is my book?”&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;If we take our roads data above—perhaps all of the roads for the United States—we could store them in a table Roads:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;Roads(name varchar(30), location geography)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;I.e., geography is a column type just like any other.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We expose a pretty comprehensive set of operations on these type through a method-based interface.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For example, if we have a geometry variable @microsoft that represents Microsoft’s main campus, we can find out which roads intersect it with the query:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;FONT face=Calibri size=3&gt;SELECT name&lt;BR&gt;FROM Roads&lt;BR&gt;WHERE location.STIntersects(@microsoft) = 1&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;Given a similar Parks table containing all US parks, we can ask our parks question from above:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;FONT face=Calibri size=3&gt;SELECT SUM(location.STArea())&lt;BR&gt;FROM Parks&lt;BR&gt;WHERE location.STDistance(@microsoft) &amp;lt; 1.0&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 11pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: Calibri; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Of course, beyond answering this query, we need to be able to answer the query quickly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since my data may be very large, speed is going to mean having a good spatial index.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Perhaps that will be the subject of my next post.&amp;nbsp; Watch this space for more.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 11pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: Calibri; mso-bidi-font-family: 'Times New Roman'; mso-ascii-theme-font: minor-latin; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&amp;nbsp;Cheers,&lt;BR&gt;-Isaac&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2681837" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/isaac/archive/tags/live+maps/default.aspx">live maps</category><category domain="http://blogs.msdn.com/isaac/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://blogs.msdn.com/isaac/archive/tags/spatial/default.aspx">spatial</category></item></channel></rss>