{"id":36024,"date":"2018-03-23T11:56:41","date_gmt":"2018-03-23T18:56:41","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=36024"},"modified":"2019-04-04T08:35:31","modified_gmt":"2019-04-04T15:35:31","slug":"performing-geospatial-calculations-azure-cosmosdb","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/performing-geospatial-calculations-azure-cosmosdb\/","title":{"rendered":"Performing Geospatial Calculations with Azure CosmosDB"},"content":{"rendered":"<p>\t\t\t\tAzure CosmosDB is a multi-model, globally distributed database, as well as a geospatial calculation powerhouse. It can calculate the distance between two points, determine whether a road runs through a city, and identify if a body of water is wholly contained within a state. In this article, you&#8217;ll learn how to unleash the potential of Azure CosmosDB so your apps can handle geographic data on a cosmic scale!<\/p>\n<p>We&#8217;ll walk through the process of adding geospatial calculations to an app that will be able to determine features contained within a boundary, what features intersect with each other, and the distance features are from a single point.<\/p>\n<p>For this post, Madison Wisconsin USA will be the location data is pulled from.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-medium\" src=\"https:\/\/res.cloudinary.com\/code-mill-technologies-inc\/image\/upload\/v1521222910\/app_fgnjjf.gif\" alt=\"Geospatial calculations in app\" width=\"264\" height=\"576\" \/><\/p>\n<h2>What is Geospatial Data?<\/h2>\n<p>Spatial data describes the position and shape of objects in space. In most apps, we&#8217;re interested in locations on Earth: the location of a landmark, the route of a road, or the boundaries of a city. This geographical, or geospatial, data can be described by using three different types of data: <strong>Points<\/strong>, <strong>Line Strings<\/strong>, and <strong>Polygons<\/strong>.<\/p>\n<ul>\n<li>A <strong>Point<\/strong> models a single longitude and latitude location; a landmark or a person&#8217;s location, for example.<\/li>\n<li>A <strong>Line String<\/strong> models several points with the lines used to connect those points, such as the path of a highway or a river.<\/li>\n<li>Finally, a <strong>Polygon<\/strong> is a boundary of connected points whose Line Strings form a closed loop. The boundaries of a city or that of a body of water are examples of Polygons.<\/li>\n<\/ul>\n<p>There are three operations you can perform with this geospatial data.\u00a0<strong>Distance<\/strong>, <strong>Intersects<\/strong>, and <strong>Within<\/strong>.<\/p>\n<ul>\n<li><strong>Distance<\/strong> determines how far away two geospatial objects are away from each other.<\/li>\n<li><strong>Intersects<\/strong> indicates whether part of one object lies within the other.<\/li>\n<li><strong>Within<\/strong> determines whether one object wholly contains another within its boundaries.<\/li>\n<\/ul>\n<p>Now that you know what geospatial data is and the operations you can perform with it, let&#8217;s see how to work with it in your Xamarin apps!<\/p>\n<h2>Working With Geospatial Data<\/h2>\n<p><em>If you don&#8217;t already know how to work with CosmosDB, check out this <a href=\"https:\/\/msou.co\/bgi\">excellent documentation<\/a> on working with CosmosDB and Xamarin apps.<\/em><\/p>\n<p>Xamarin apps accesses CosmosDB with the\u00a0<a href=\"https:\/\/msou.co\/bgj\">Microsoft.Azure.DocumentDB NuGet<\/a>\u00a0package (the DocumentDB refers to one of the underlying databases that CosmosDB supports). The NuGet package contains several classes that model the geospatial types mentioned above, and the classes contain helper methods which perform the various operations on geospatial data.<\/p>\n<p>The app we&#8217;re building works with the following geospatial features:<\/p>\n<p><img decoding=\"async\" class=\"size-medium aligncenter\" src=\"https:\/\/res.cloudinary.com\/code-mill-technologies-inc\/image\/upload\/c_scale,h_600\/v1521218867\/Screen_Shot_2018-03-16_at_11.36.26_AM_se7mjf.png\" alt=\"Geospatial features in the app\" width=\"458\" height=\"600\" \/><\/p>\n<p>There are polygons to represent the entire state of Wisconsin, the city of Madison, the city of Milwaukee, and the city of Chicago. Line strings represent major highways. Finally, there&#8217;s a single point to represent the location of an annual Cheese Curd Festival (because it&#8217;s Wisconsin and they love cheese! \ud83e\uddc0). Each of these locations will be referred to as features. You can view this in CosmosDB by clicking <a href=\"https:\/\/msou.co\/bgq\">here<\/a>.<\/p>\n<p>By picking a feature, and then a spatial operation, you&#8217;re able to determine which highways and cities intersect each other, or which cities contain which highways, or even how far a city is away from the Cheese Festival (very important)! There are many combinations of what one can do.<\/p>\n<h3>Selecting a Feature<\/h3>\n<p>The first thing the app needs to do is select a feature. It does so with the following code:<\/p>\n<pre class=\"lang:c# decode:true\">\/\/ collectionURI is a URI pointing to the CosmosDB collection\nvar featureQuery = client.CreateDocumentQuery&lt;Feature&gt;(collectionUri)\n                         .Where(f =&gt; f.LocationName == featureName)\n                         .Take(1)\n                         .AsDocumentQuery();<\/pre>\n<p>This is a common CosmosDB query for finding a document and follows <a href=\"https:\/\/msou.co\/bgk\">the documentation<\/a> closely. From here on out, the returned document will be used in the other operations as the feature to compare against.<\/p>\n<h3>Finding the Distance<\/h3>\n<p>Let&#8217;s start with the most important question, the distance of the features to the Cheese Curd Festival!<\/p>\n<pre class=\"lang:c# decode:true\">\/\/ cheeseFestival is a Point\nvar distanceQuery = client.CreateDocumentQuery&lt;Feature&gt;(collectionUri)\n    .Where(f =&gt; f.Id == feature.Id) \/\/ feature is what you want to find out how far away it is\n    .Select(f =&gt; cheeseFestival.Distance(f.Location)) \/\/ Location is a Geometry type\n    .AsDocumentQuery();<\/pre>\n<p>That&#8217;s it! The base class for all geospatial objects,\u00a0<code>Microsoft.Azure.Documents.Spatial.Geometry<\/code>\u00a0contains a\u00a0<code>Distance<\/code>\u00a0function which will tell CosmosDB to figure out the distances between all the various geometries and the point\/return that as a\u00a0<code>double<\/code>.<\/p>\n<p>Pull the results from the <span class=\"lang:c# decode:true crayon-inline \">DocumentQuery<\/span>\u00a0exactly as you normally would.<\/p>\n<h3>Finding Intersections<\/h3>\n<p>The following code finds everything in the database that crosses paths or intersects with the passed-in\u00a0<code>feature<\/code>:<\/p>\n<pre class=\"lang:c# decode:true \">var intersectingQuery = client.CreateDocumentQuery&lt;Feature&gt;(collectionUri)\n      .Where(f =&gt; feature.Id != f.Id) \/\/ Ignore passed in\n      .Where(f =&gt; feature.Location.Intersects(f.Location))                  \n      .AsDocumentQuery();<\/pre>\n<p>That&#8217;s all there is to it! This will find everything in the database that intersects with the passed in feature.<\/p>\n<h3>Finding Features Contained Within<\/h3>\n<p>By now, you may be able to guess how this is done. There&#8217;s a\u00a0<code>Within<\/code>\u00a0function that determines which objects are wholly contained within another. The code looks like this:<\/p>\n<pre class=\"lang:c# decode:true \">var withinQuery = client.CreateDocumentQuery&lt;Feature&gt;(collectionUri)\n      .Where(f =&gt; feature.Id != f.Id) \/\/ Ignore passed in\n      .Where(f =&gt; f.Location.Within(feature.Location))                                      \n      .AsDocumentQuery();<\/pre>\n<p>The best part? These queries return lightning fast, even though there are many points, line strings, and polygons being queried!<\/p>\n<h2>Next Steps<\/h2>\n<p>You can view the full code for this sample <a href=\"https:\/\/msou.co\/bgl\">here<\/a>. There&#8217;s also ample documentation for spatial operation in Azure CosmosDB on <a href=\"https:\/\/msou.co\/bgm\">docs.microsoft.com<\/a>, and a recently completed app that makes use of CosmosDB&#8217;s spatial features plus a number of other Azure offerings <a href=\"https:\/\/msou.co\/bgn\">here<\/a>.<\/p>\n<p>The best thing to do, though, is trying it for yourself! Create a <a href=\"https:\/\/msou.co\/bgo\">free Azure account<\/a>\u00a0(with enough credit to use CosmosDB for a year!), <a href=\"https:\/\/msou.co\/bgp\">set up a CosmosDB instance<\/a>, and start creating your own spatially aware database today!<\/p>\n<p>Have questions or comments about this post? <a href=\"https:\/\/forums.xamarin.com\/124388\/performing-geospatial-calculations-with-azure-cosmosdb\">Chat about it in the Xamarin Forums.<\/a>\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Azure CosmosDB is a multi-model, globally distributed database, as well as a geospatial calculation powerhouse. It can calculate the distance between two points, determine whether a road runs through a city, and identify if a body of water is wholly contained within a state. In this article, you&#8217;ll learn how to unleash the potential of [&hellip;]<\/p>\n","protected":false},"author":569,"featured_media":39167,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[4],"class_list":["post-36024","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>Azure CosmosDB is a multi-model, globally distributed database, as well as a geospatial calculation powerhouse. It can calculate the distance between two points, determine whether a road runs through a city, and identify if a body of water is wholly contained within a state. In this article, you&#8217;ll learn how to unleash the potential of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/36024","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/569"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=36024"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/36024\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=36024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=36024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=36024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}