<?xml version="1.0" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">

	<channel>
		<title>ThinkGeo and Map Suite White Papers</title>
		<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/afv/topicsview/Default.aspx</link>
		<description>In-depth research and documentation on Map Suite 2.0 technologies.</description>
		<language>en-US</language>
		<generator>ActiveForums  4.0</generator>
		<copyright>Copyright 2003-2008 ThinkGeo LLC</copyright>
		<lastBuildDate>Thu, 13 Nov 2008 05:48:51 GMT</lastBuildDate><image><url>http://gis.thinkgeo.com/Portals/1/logo.png</url><title>ThinkGeo and Map Suite White Papers</title><link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/afv/topicsview/Default.aspx</link></image>
		<item>
			<title>How To Use the Map Rotation Feature in Map Suite 2.53.5</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;After hearing many requests for Map Rotation functionality from the Map Suite user community, we decided to add that feature to Map Suite starting with version 2.53. We approached the goal of having the entire map rotate from the center of its current extent at will through a Projection class called &lt;tt&gt;Rotated&lt;/tt&gt;.  In other words, from the developer's perspective, Map Rotation is simply applying a Projection class to all the Layers and MapShapes, and letting Map Suite take care of everything else automatically.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; For the purposes of this article we have used the Map Suite Desktop Edition to demonstrate Map Rotation, but please note that Map Rotation functionality is also available in the Map Suite Web and Engine editions.&lt;/p&gt;

&lt;h3&gt;Applying Map Rotation&lt;/h3&gt;

&lt;p&gt;For the developer, applying Map Rotation is very straightforward.  Essentially, all vector data (Layers and MapShapes) need to have their projection property set to the projection class &lt;tt&gt;Rotated&lt;/tt&gt;.  But before we do that, we need to declare a form level variable for &lt;tt&gt;Rotated&lt;/tt&gt;.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private mRotated As New MapSuite.Geometry.Rotated()&lt;/code&gt;

&lt;p&gt;We will use &lt;tt&gt;mRotated&lt;/tt&gt; as the projection  for all the Layers and MapShapes of the Map. It is very important that each time you add a new Layer or MapShape to the Map, you apply the &lt;tt&gt;Rotated&lt;/tt&gt; projection to it. Otherwise, the Map Rotation will not apply to that object.&lt;/p&gt;

&lt;p&gt;For a Layer, we add it to the Map the following way:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Dim Layer1 As New Layer(&quot;..\MyLayer.shp&quot;, mRotated, False)&lt;/code&gt;

&lt;p&gt;For a MapShape, we simply set the Projection property to &lt;tt&gt;Rotated&lt;/tt&gt;:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;PointMapShape1.Projection = mRotated&lt;/code&gt;

&lt;p&gt;Now, with all the Layers and MapShapes having their Projection property set to &lt;tt&gt;Rotated&lt;/tt&gt;, we are ready to have the Map Rotation take effect. Each time the map has to rotate, we use the &lt;tt&gt;SetAngle&lt;/tt&gt; method of &lt;tt&gt;Rotated&lt;/tt&gt;.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Map1.CurrentExtent = mRotated.SetAngle(90, Map1.CurrentExtent)&lt;/code&gt;

&lt;p&gt;You can rotate the Map from 0 to 360 degrees counterclockwise by using positive values, or clockwise by using negative values.  So for example, 90 and -270 will have the same effect.&lt;/p&gt;

&lt;p&gt;If you want to rotate incrementally, for example by 10 degrees at a time, you can use the &lt;tt&gt;GetAngle&lt;/tt&gt; property and add 10 as the Angle parameter of &lt;tt&gt;SetAngle&lt;/tt&gt;. Here we are rotating the map by increment of 10 degrees counterclockwise.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Map1.CurrentExtent = mRotated.SetAngle(mRotated.GetAngle + 10, Map1.CurrentExtent)&lt;/code&gt;

&lt;h3&gt;Keeping the Bearings&lt;/h3&gt;

&lt;p&gt;As the Map rotates, it is important to keep bearings and to know where the North is. That is why drawing a North Arrow that always points to the north helps prevent you from getting disoriented. Below is a trick that can be used to draw a bitmap of a North Arrow that always points to the North.&lt;/p&gt;

&lt;p&gt;First, declare a form level variable for the North Arrow bitmap.  Then, in the &lt;tt&gt;AfterMapDraw&lt;/tt&gt; event of the Map, you can write the logic for the rotation:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private Sub Map1_AfterMapDraw(ByVal g As System.Drawing.Graphics) Handles Map1.AfterMapDraw
        Dim Matrix As New Matrix
        Dim ImageX, ImageY, ImageWidth, ImageHeight As Integer
        ImageX = 30 : ImageY = 30 : ImageWidth = 56 : ImageHeight = 69
        Dim pt As New PointF(ImageX + (ImageWidth / 2), ImageY + (ImageHeight / 2))
        Matrix.RotateAt(CSng(-mRotated.GetAngle), pt)
        g.Transform = Matrix
        g.DrawImage(mNorthArrowBitmap, ImageX, ImageY, ImageWidth, ImageHeight)
        g.Dispose()
End Sub
&lt;/code&gt;

&lt;p style=&quot;margin-top:20px;&quot;&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapRotation_01.jpg&quot; alt=&quot;Figure 1&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 1: Street Map with Angle set at 0.&lt;/small&gt;
&lt;/p&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapRotation_02.jpg&quot; alt=&quot;Figure 2&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 2: Street Map with Angle set at 132. See how the North Arrow tilted to point to the North.&lt;/small&gt;
&lt;/p&gt;

&lt;p&gt;In the included &lt;a href=&quot;http://gis.thinkgeo.com/download/MapRotationDemo.zip&quot;&gt;demo application&lt;/a&gt;, we show you two ways to rotate the map. One is by using a Button control where the angle of Map is changed, by a user defined increment, clockwise and counterclockwise. The other method is by using a Roll control that serves as a compass, where you can set the angle of the map using the mouse.  &lt;a href=&quot;http://gis.thinkgeo.com/download/MapRotationDemo.zip&quot;&gt;Download the demo application&lt;/a&gt; to see both methods in action.  (Please note that the demo requires the free evaluation of the Map Suite Desktop GIS .NET control, &lt;a href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot;&gt;available here&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Another important thing to take into account is the coordinates we get on the Map by rotating it. If we always want to have the real coordinates and not the coordinates from the rotation, we are going to use the &lt;tt&gt;ProjectPointBack&lt;/tt&gt; method of &lt;tt&gt;Rotated&lt;/tt&gt;. The code below will show the real coordinates from the &lt;tt&gt;MouseMove&lt;/tt&gt; event on the status bar:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private Sub Map1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Map1.MouseMove
        Dim RotWorldPointR As PointR = Map1.ToWorldCoordinate(e.X, e.Y)
        Dim RealWorldPointR As PointR = mRotated.ProjectPointBack(RotWorldPointR.X, RotWorldPointR.Y)
        StatusBar1.Panels(0).Text = &quot;X: &quot; &amp; RealWorldPointR.X &amp; &quot;  Y: &quot; &amp; RealWorldPointR.Y
        StatusBar1.Panels(1).Text = DecimalDegrees.DecimalDegreesToDMS(RealWorldPointR)
End Sub
&lt;/code&gt;

&lt;h3&gt;Ruminations&lt;/h3&gt;

&lt;p&gt;Taking the idea of Map Rotation further, nothing stops us from displaying the world with the North down, the South up, the East to the left and the West to the right by applying a 180 angle to the &lt;tt&gt;Rotated&lt;/tt&gt; projection:&lt;/p&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapRotation_03.jpg&quot; alt=&quot;Figure 3&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080; line-height:120%;&quot;&gt;Fig 3. The World with the South on top. This map was created by applying an angle of 180 degrees to a few of the ShapeFiles that come with the &lt;a href=&quot;http://gis.thinkgeo.com/Products/MapDatasetPluginsforNETDevelopers/RenderWorld/tabid/177/Default.aspx&quot;&gt;Render World&lt;/a&gt; product.&lt;/small&gt;
&lt;/p&gt;

&lt;p&gt;The map shown above will probably shock many of us, but although this is an unconventional view of the world, it is completely accurate scientifically and it is not breaking any cartographic rules.&lt;/p&gt;

&lt;p&gt;Below are the scientific definitions of the four cardinal directions:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;East:&lt;/b&gt; The direction toward which the Earth rotates about its axis (therefore the direction from which the Sun appears to rise)&lt;/p&gt;

&lt;p&gt;&lt;b&gt;West:&lt;/b&gt; The direction opposite to that of the Earth's rotation axis (therefore the direction towards which the Sun appears to set)&lt;/p&gt;

&lt;p&gt;&lt;b&gt;South:&lt;/b&gt; The direction along the earth's surface toward the pole that is on one's right at the Equator when facing the direction toward which the Earth rotates about its axis (East).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;North:&lt;/b&gt; The direction along the earth's surface toward the pole that is on one's left at the Equator when facing the direction toward which the Earth rotates about its axis (East).&lt;/p&gt;

&lt;p&gt;So according to those definitions, there is no reason why the North must be placed on top. The reason it seems odd to many of us is due to our own western bias, where North has always historically been used as a fundamental direction, placing Europe on the top of the map. But this is completely arbitrary.&lt;/p&gt;

&lt;p&gt;Even the magnetic north, which is the direction along the earth's surface in which horizontal magnetic field strength has its most positive value, is a very transitional thing. Due to the “flipping” of the magnetic poles, perhaps in a few thousand years, the magnetic pole will later lie in the southern hemisphere.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Map Suite developers can now take advantage of Map Rotation to add a totally new dimension of map display to their GIS applications.  Currently, Map Rotation applies only to vector data, Layers and MapShapes, not ImageLayers or GRIDs. We are aware that this is a limitation. The next major release of Map Suite, version 3.0, is planned to support Map Rotation for any data, vector or raster image.&lt;/p&gt;

&lt;h3&gt;Downloads&lt;/h3&gt;

&lt;ul style=&quot;list-style-type:none; margin-left:0; padding-left:0;&quot;&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:9px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/download/MapRotationDemo.zip&quot; style=&quot;padding-left:20px; background:url(/portals/1/icons/icon_download_2.gif) no-repeat left center;&quot;&gt;&lt;b&gt;Download Map Rotation Demo Application&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none;&quot;&gt;&lt;b&gt;Note: You will need to download the &lt;a href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot;&gt;Map Suite Desktop .NET GIS Control Free Evaluation&lt;/a&gt; in order to run the example in this article.&lt;/b&gt; (Registration Required)&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;Have Questions?&lt;/h3&gt;

&lt;p&gt;Do you have any questions or comments about this article?  If so, feel free post your questions on the &lt;a href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/Default.aspx&quot;&gt;Map Suite Discussion Forums&lt;/a&gt; or leave feedback at the &lt;a href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/afv/topicsview/aff/16/Default.aspx&quot;&gt;ThinkGeo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Additional Resources&lt;/h3&gt;

&lt;ul style=&quot;list-style-type:none; margin-left:0; padding-left:0;&quot;&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/QuickStartGuides/tabid/197/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite QuickStart Guides&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/APIDocumentation/tabid/194/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite API Documentation&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/FAQs/tabid/196/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite FAQs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;About the Author&lt;/h3&gt;

&lt;p&gt;Val Guillou is a GIS analyst and developer at ThinkGeo, a software company specializing in geospatial software with an emphasis on software development tools and GPS tracking solutions.&lt;/p&gt;</description>
			<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4785/afv/topic/Default.aspx</link>
			<dc:creator>ThinkGeo</dc:creator>
			<pubDate>Thu, 13 Nov 2008 05:48:51 GMT</pubDate>
			<guid>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4785/afv/topic/Default.aspx</guid>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>How To Use GRID with Map Suite</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;This article will introduce the &lt;a href=&quot;http://gis.thinkgeo.com&quot;&gt;Map Suite&lt;/a&gt; developer community to the GRID format and help demonstrate how useful GRID can be. GRID can come handy in numerous situations where you need to create custom map displays, perform interpolation or do spatial analysis. We hope that by reading this article you will see more clearly how to apply GRID to your own industry and reap the benefits it provides.                                  &lt;/p&gt;&lt;/div&gt;

&lt;h3&gt;Introduction&lt;/h3&gt;

&lt;p&gt;For the purposes of this article we have used the Map Suite Desktop Edition to show the functionality of GRID, but please note that GRID functionality is also available in the Map Suite Web and Engine editions.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; This article is meant to be used as a tutorial for using GRID as a GIS technique, not as a definitive tool for soil analysis. The soil quality examples included here are fictitious, and the soil quality calculations based on pH and Magnesium levels do not come from an authoritative source in agriculture.&lt;/p&gt;

&lt;h3&gt;GRID Explained&lt;/h3&gt;

&lt;p&gt;A GRID is a raster format that defines a geographic space as an array of equally sized squares (cells) arranged in rows and columns. Each cell stores a numeric value that represents a geographic attribute (such as elevation, surface slope, soil pH, etc.) for that unit of space. Each grid cell is referenced by its x, y coordinate location.&lt;/p&gt;

&lt;h3&gt;File Format&lt;/h3&gt;

&lt;p&gt;The format of the GRID file is  ASCII and contains two main parts, the header and the body. The header consists of the first few lines for references of the grid such as the number of columns, the number of rows, the x and y coordinate of the lower left of the grid, the cell size and the no data value (which will be used in the body of the GRID file to represent a null value). The body contains the cell values listed in the order they would naturally appear from left to right and from top to bottom.&lt;/p&gt;

&lt;h4&gt;Example of ASCII GRID Format:&lt;/h4&gt;

&lt;pre&gt;
ncols         4
nrows         6
xllcorner     0.0
yllcorner     0.0
cellsize      50.0
NODATA_value  -9999
-9999 -9999 5 2
-9999 20 100 36
3 8 35 10
32 42 50 6
88 75 27 9
13 5 1 -9999
etc...
&lt;/pre&gt;


&lt;h3&gt;Getting Started&lt;/h3&gt;

&lt;p&gt;Now that we have covered the theory of the GRID, we are going to use a very concrete example to show how useful GRID can be in practical GIS applications.&lt;/p&gt;

&lt;p&gt;Let's say that we have a point-based shapefile representing some sample points where the pH (acidity level) of the soil was measured on a field.&lt;/p&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/GRID_01.png&quot; alt=&quot;Sample Application Screenshot&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 1: Point-based shapefile of sample pH levels.&lt;/small&gt;
&lt;/p&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/GRID_02.png&quot; alt=&quot;Legend&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 2: Map legend.&lt;/small&gt;
&lt;/p&gt;

&lt;p&gt;Now with those few sample points, we want the entire field to be covered with a pH value. This is when GRID comes in handy. Using an interpolation method, IDW (Inverse Distance Weighing), we will create a GRID and then display it on the map to show clearly the different pH values throughout the field.&lt;/p&gt;

&lt;h3&gt;Creating the GRID&lt;/h3&gt;

&lt;p&gt;Before creating the GRID, we need to decide the extent of the grid, the size of the cells and the value for no data. In our case, we are going to take a slightly larger extent of the field and we are going to have a cell size of 0.0001 (we are in decimal degrees, so 0.0001 degrees are about 9.6 meters). The no data value is -9999. This means that any cell that is outside the field (where the pH value is irrelevant), we will assign it the -9999 value.&lt;/p&gt;

&lt;p&gt;In the Click event of a Button, we will write the logic to create the GRID.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private Sub btnIDW_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnIDW.Click
        Dim gridExtent As New StraightRectangle(Map1.CurrentExtent)
        Dim cellSize As Double = 0.0001
        Dim NoDataValue As Double = -9999

        AddHandler GridLayer.CalculateCellValue, AddressOf CalculateCellValueHandlerIDW
        Dim Result As Boolean = GridLayer.CreateGridFile(&quot;..\PHIDW_2_200_A.grd&quot;, gridExtent, cellSize, NoDataValue)

        If Result = True Then
            MessageBox.Show(&quot;Grid File saved successfully.&quot;, &quot;Information&quot;, MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            MessageBox.Show(&quot;Saving Grid File Failed.&quot;, &quot;Information&quot;, MessageBoxButtons.OK, MessageBoxIcon.Information)
        End I
    End Sub
&lt;/code&gt;

&lt;p&gt;At the creation of the GRID, the event CalculateCellValue is going to be raised for each cell to assign a value. So we are going to write the interpolation algorithm in the handler CalculateCellValueHandlerIDW. In our example, we are using IDW interpolation, or Inverse Distance Weighing. This is a common method for interpolation that assigns values to unknown locations based on some scattered set of known points – which is exactly the case in our example. This interpolation has two variables: The number of points to take into account (based on distance) and the power parameter. Playing with those two variables is going to give a result with smoother or sharper peaks.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Notes:&lt;/b&gt; We are using IDW interpolation in this example, but you are free to use any other type of interpolation or algorithm to calculate the cell value. For more information on interpolation, check the following site: &lt;a href=&quot;http://en.wikipedia.org/wiki/Multivariate_interpolation&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://en.wikipedia.org/wiki/Multivariate_interpolation&lt;/a&gt;&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private Sub CalculateCellValueHandlerIDW(ByVal CellExtent As StraightRectangle, ByRef CellValue As Double)
        Dim CellULx As Double = CellExtent.UpperLeftPoint.X
        Dim CellULy As Double = CellExtent.UpperLeftPoint.Y
        Dim CellLRx As Double = CellExtent.LowerRightPoint.X
        Dim CellLRy As Double = CellExtent.LowerRightPoint.Y

        Dim xp As Double = CellExtent.Center.X
        Dim yp As Double = CellExtent.Center.Y
        Dim CellCenterPointShape As New PointShape(xp, yp)
        Dim CenterRecords() As Integer = Map1.Layers(0).QueryByDistance(CellExtent, 15, MapLengthUnits.metres, Map1.MapUnit)

        If CenterRecords.GetLength(0) = 1 Then

            Dim NearestRecords() As Integer = Map1.Layers(1).QueryByDistance(CellCenterPointShape, 200, MapLengthUnits.metres, Map1.MapUnit)
            If NearestRecords.GetLength(0) &gt; 0 Then
                Dim NearestPointShapes() As PointShape = CType(Map1.Layers(1).GetShapes(NearestRecords), PointShape())
                Dim NearestValues(NearestRecords.GetLength(0) - 1) As String
                For i As Integer = 0 To NearestRecords.GetLength(0) - 1
                    NearestValues(i) = Map1.Layers(1).DataQuery(NearestRecords(i), &quot;pH&quot;)
                Next i
                'This is the algorithm for IDW interpolation
                Dim Power As Double = 2
                Dim Zi, Zx1, Zx2, Zx, Di As Double
                For i As Integer = 0 To NearestValues.GetLength(0) - 1
                    Zi = CDbl(NearestValues(i))
                    Di = CellCenterPointShape.DistanceTo(NearestPointShapes(i), Map1.MapUnit, MapLengthUnits.metres, DistanceTypes.Shortest)
                    Zx1 = Zx1 + (Math.Pow((1 / Di), Power) * (Zi))
                    Zx2 = Zx2 + ((Math.Pow((1 / Di), Power)))
                Next
                Zx = Zx1 / Zx2
                CellValue = Zx
            Else
                CellValue = -9999
            End If
        Else
            CellValue = -9999
        End If
    End Sub
&lt;/code&gt;

&lt;p&gt;In our example, we are using a distance of 200 meters to get the sample points within that distance and we are using a power of 2. By specifying a higher power, more emphasis is placed on the nearest points, giving a smoother result. By specifying a lower power, more influence is placed on the points that are farther away, giving a sharper result.&lt;/p&gt;

&lt;h3&gt;Displaying the GRID&lt;/h3&gt;

&lt;p&gt;Now that we have the GRID created, we need to display it. This article will demonstrate two different ways of displaying the GRID.  For the first way, we will apply a specific color to any cell belonging to a certain class. The second method uses a gradient to go from one color to another. The purpose is to show different ways one GRID can be displayed.&lt;/p&gt;

&lt;h3&gt;Using ClassBreaks&lt;/h3&gt;

&lt;p&gt;We are going to display the cells of the GRID in the same way as we did for the original shapefile of sample points. Note that you might want to remove the two shapefiles from the Map so that they do not appear on top of the GRID.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Dim STR_GridFile As String = &quot;..\SoilQuality.grd&quot;
        Dim gridlayer As GridLayer = New GridLayer(STR_GridFile)
        gridlayer.LowerThreshold = 0
        gridlayer.UpperThreshold = Double.MaxValue
        gridlayer.ThresholdUnit = ThresholdUnits.miles
        gridlayer.IsNonValueTransparent = True
        Dim gridranges As RangeCollection = New RangeCollection()
        gridranges.Add(New Range(7.54, 7.9, Color.FromArgb(0, 255, 0)))
        gridranges.Add(New Range(7.21, 7.54, Color.FromArgb(128, 255, 128)))
        gridranges.Add(New Range(7.15, 7.21, Color.FromArgb(224, 251, 132)))
        gridranges.Add(New Range(7.08, 7.15, Color.FromArgb(225, 255, 0)))
        gridranges.Add(New Range(7.0, 7.08, Color.FromArgb(245, 210, 10)))
        gridranges.Add(New Range(6.83, 7.0, Color.FromArgb(255, 128, 0)))
        gridranges.Add(New Range(6.2, 6.83, Color.FromArgb(255, 0, 0)))
        gridlayer.Ranges = gridranges

        Map1.GridLayers.Add(gridlayer)
&lt;/code&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/GRID_03.png&quot; alt=&quot;Sample Application Screenshot&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 3: GRID resulting from sample points interpolation displayed with Class Breaks.&lt;/small&gt;
&lt;/p&gt;

&lt;h3&gt;Using Gradient&lt;/h3&gt;

&lt;p&gt;We are going to display the cells of the GRID with a gradient going progressively from red (for low pH) to green (for high pH). Note that in addition to Map, Layer (the vector shapefile layer) has a GRIDLayers collection so that GRID files can be displayed in the desired order. Here we are displaying the GRID file between the Field Layer and the sample points Layer.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Dim STR_GridFile As String = &quot;..\SoilQuality.grd&quot;
        Dim gridlayer As GridLayer = New GridLayer(STR_GridFile)
        gridlayer.LowerThreshold = 0
        gridlayer.UpperThreshold = Double.MaxValue
        gridlayer.ThresholdUnit = ThresholdUnits.miles
        gridlayer.IsNonValueTransparent = True
        Dim gridranges As RangeCollection = New RangeCollection()

        Dim Alpha As Integer = 255
        gridranges.Add(New GradientRange(6.2, Color.FromArgb(Alpha, Color.FromArgb(255, 0, 0)), 7.9, Color.FromArgb(Alpha, Color.FromArgb(0, 255, 0))))
        gridlayer.Ranges = gridranges
     Map1.Layers(0).GridLayers.Add(gridlayer)
&lt;/code&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/GRID_04.png&quot; alt=&quot;Sample Application Screenshot&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 4: GRID resulting from sample points interpolation displayed with gradient. The Layer with the sample points appears on top.&lt;/small&gt;
&lt;/p&gt;

&lt;h3&gt;Multi GRID operations&lt;/h3&gt;

&lt;p&gt;One of the big advantages of GRID is to be able to create a new GRID by analyzing and performing calculations on the cell values of an existing GRID, or by combining two existing GRIDs to create a third one. For our next example,  we have a second GRID that represents Magnesium levels throughout the field from 40 to 95 ppm.  We will combine the pH value GRID and the Magnesium level GRID to create a third, composite GRID.&lt;/p&gt;

&lt;h3&gt;Displaying the GRID for Magnesium&lt;/h3&gt;

&lt;p&gt;We are going to display the GRID Magnesium_Level using a gradient. (This previously-created GRID is supplied to us for the purpose of this example.)&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Dim STR_GridFile As String = &quot;..\Magnesium_Level.grd&quot;
        Dim gridlayer As GridLayer = New GridLayer(STR_GridFile)
        gridlayer.LowerThreshold = 0
        gridlayer.UpperThreshold = Double.MaxValue
        gridlayer.ThresholdUnit = ThresholdUnits.miles
        gridlayer.IsNonValueTransparent = True
        Dim gridranges As RangeCollection = New RangeCollection()
        gridranges.Add(New GradientRange(40, Color.FromArgb(254, 215, 186), 90,    Color.FromArgb(105, 46, 1)))
        gridlayer.Ranges = gridranges
        Map1.Layers(0).GridLayers.Add(gridlayer)
&lt;/code&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/GRID_05.png&quot; alt=&quot;Sample Application Screenshot&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 5: GRID of Magnesium level in PPM from 40 to 95. The darker color the higher the value.&lt;/small&gt;
&lt;/p&gt;

&lt;h3&gt;Creating a third GRID from pH GRID and Magnesium GRID&lt;/h3&gt;

&lt;p&gt;For our example crop, the combination of a pH value between 7.0 and 7.5 and a high magnesium level represents the best soil. The resulting GRID will represent soil quality for that crop by combining the two GRIDs.  The cell values will be calculated according to a common formula used by agricultural engineers.  We attribute a factor for each pH value and Magnesium level, then we combine the two factors to get the soil quality for that crop.&lt;/p&gt;

&lt;div style=&quot;float:left; margin-right:50px;&quot;&gt;
&lt;table cellpadding=&quot;5&quot; cellspacing=&quot;0&quot; border=&quot;1&quot; bordercolor=&quot;#808080&quot; style=&quot;border-collapse:collapse;&quot;&gt;
&lt;tr style=&quot;background-color:#ddd;&quot;&gt;
	&lt;th&gt;pH Level&lt;/th&gt;
	&lt;th&gt;Factor&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;6.20 to 6.40&lt;/td&gt;
	&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;6.40 to 6.60&lt;/td&gt;
	&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;6.60 to 6.80&lt;/td&gt;
	&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;6.80 to 7.00&lt;/td&gt;
	&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;7.00 to 7.20&lt;/td&gt;
	&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;7.20 to 7.40&lt;/td&gt;
	&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;7.40 to 7.60&lt;/td&gt;
	&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;7.60 to 7.80&lt;/td&gt;
	&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;7.80 to 8.00&lt;/td&gt;
	&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p style=&quot;margin-top:3px;&quot;&gt;&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Table 1: pH factors&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;div style=&quot;float:left;&quot;&gt;
&lt;table cellpadding=&quot;5&quot; cellspacing=&quot;0&quot; border=&quot;1&quot; bordercolor=&quot;#808080&quot; style=&quot;border-collapse:collapse;&quot;&gt;
&lt;tr style=&quot;background-color:#ddd;&quot;&gt;
	&lt;th&gt;Mg Level&lt;/th&gt;
	&lt;th&gt;Factor&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;40 to 45&lt;/td&gt;
	&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;45 to 50&lt;/td&gt;
	&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;50 to 55&lt;/td&gt;
	&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;55 to 60&lt;/td&gt;
	&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;60 to 65&lt;/td&gt;
	&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;65 to 70&lt;/td&gt;
	&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;70 to 75&lt;/td&gt;
	&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;75 to 80&lt;/td&gt;
	&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;80 to 85&lt;/td&gt;
	&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;85 to 90&lt;/td&gt;
	&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p style=&quot;margin-top:3px;&quot;&gt;&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Table 2: Mg factors&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p style=&quot;clear:left;&quot; /&gt;To determine the soil quality, we will combine the pH factor with the Mg factor. For example, if the pH is 6.67 and the Mg level is 55, the soil quality index will be 28 (7 * 4). The soil quality index goes from a minimum of 5 to a maximum of 100.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private Sub btnSoilQuality_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSoilQuality.Click
        Dim gridExtent As New StraightRectangle(Map1.Layers(0).GridLayers(0).Extent)
        Dim cellSize As Double = 0.0001
        Dim NoDataValue As Double = -9999

        AddHandler GridLayer.CalculateCellValue, AddressOf CalculateCellValueSoilQuality

        Dim Result As Boolean = GridLayer.CreateGridFile(&quot;..\SoilQuality.grd&quot;, gridExtent, cellSize, NoDataValue)

        If Result = True Then
            MessageBox.Show(&quot;Grid File saved successfully.&quot;, &quot;Information&quot;, MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            MessageBox.Show(&quot;Saving Grid File Failed.&quot;, &quot;Information&quot;, MessageBoxButtons.OK, MessageBoxIcon.Information)
        End If
    End Sub

Private Sub CalculateCellValueSoilQuality(ByVal CellExtent As StraightRectangle, ByRef CellValue As Double)
        Dim CellULx As Double = CellExtent.UpperLeftPoint.X
        Dim CellULy As Double = CellExtent.UpperLeftPoint.Y
        Dim CellLRx As Double = CellExtent.LowerRightPoint.X
        Dim CellLRy As Double = CellExtent.LowerRightPoint.Y

        Dim xp As Double = CellExtent.Center.X
        Dim yp As Double = CellExtent.Center.Y
        Dim CellCenterPointShape As New PointShape(xp, yp)

        Dim pHValue As Double = Map1.Layers(0).GridLayers(0).GetCellValue(xp, yp)
        Dim MgValue As Double = Map1.Layers(0).GridLayers(1).GetCellValue(xp, yp)

        If pHValue &lt;&gt; -9999 And MgValue &lt;&gt; -9999 Then
            CellValue = GetSoilQualityIndex(pHValue, MgValue)
        Else
            CellValue = -9999
        End If
    End Sub

Private Function GetSoilQualityIndex(ByVal pHValue As Double, ByVal MgValue As Double) As Double
        Dim pHFactor, MgFactor As Integer
      
        If pHValue &lt; 6.4 Then
            pHFactor = 5
        ElseIf pHValue &lt; 6.6 Then
            pHFactor = 6
        ElseIf pHValue &lt; 6.8 Then
            pHFactor = 7
        ElseIf pHValue &lt; 7.0 Then
            pHFactor = 8
        ElseIf pHValue &lt; 7.2 Then
            pHFactor = 9
        ElseIf pHValue &lt; 7.4 Then
            pHFactor = 10
        ElseIf pHValue &lt; 7.6 Then
            pHFactor = 9
        ElseIf pHValue &lt; 7.8 Then
            pHFactor = 8
        Else
            pHFactor = 7
        End If

        If MgValue &lt; 45 Then
            MgFactor = 1
        ElseIf MgValue &lt; 50 Then
            MgFactor = 2
        ElseIf MgValue &lt; 55 Then
            MgFactor = 3
        ElseIf MgValue &lt; 60 Then
            MgFactor = 4
        ElseIf MgValue &lt; 65 Then
            MgFactor = 5
        ElseIf MgValue &lt; 70 Then
            MgFactor = 6
        ElseIf MgValue &lt; 75 Then
            MgFactor = 7
        ElseIf MgValue &lt; 80 Then
            MgFactor = 8
        ElseIf MgValue &lt; 85 Then
            MgFactor = 9
        Else
            MgFactor = 10
        End If

        Return pHFactor * MgFactor

    End Function
&lt;/code&gt;

&lt;p&gt;Now that we have created the GRID for Soil Quality, we are ready to display it.&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Dim STR_GridFile As String = &quot;..\SoilQuality.grd&quot;
        Dim gridlayer As GridLayer = New GridLayer(STR_GridFile)
        gridlayer.LowerThreshold = 0
        gridlayer.UpperThreshold = Double.MaxValue
        gridlayer.ThresholdUnit = ThresholdUnits.miles
        gridlayer.IsNonValueTransparent = True
        Dim gridranges As RangeCollection = New RangeCollection()
        gridranges.Add(New Range(0, 25, Color.FromArgb(216, 253, 193)))
        gridranges.Add(New Range(25, 40, Color.FromArgb(182, 251, 140)))
        gridranges.Add(New Range(40, 55, Color.FromArgb(137, 248, 71)))
        gridranges.Add(New Range(55, 70, Color.FromArgb(96, 239, 10)))
        gridranges.Add(New Range(70, 85, Color.FromArgb(75, 188, 7)))
        gridranges.Add(New Range(85, 100, Color.FromArgb(52, 131, 5)))
        gridlayer.Ranges = gridranges
        Map1.Layers(0).GridLayers.Add(gridlayer)
&lt;/code&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/GRID_06.png&quot; alt=&quot;Sample Application Screenshot&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 6: GRID for soil quality.&lt;/small&gt;
&lt;/p&gt;

&lt;p&gt;
	&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/GRID_07.png&quot; alt=&quot;Legend&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999; margin-bottom:5px;&quot; /&gt;&lt;br/&gt;
	&lt;small style=&quot;font-size:11px; color:#808080;&quot;&gt;Fig 7: Soil quality map legend.&lt;/small&gt;
&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;We hope that the simple examples in this article have shown you more clearly how GRID can help you perform and enhance various tasks in your industry. Keep in mind that the examples shown are very simplistic and that GRID is capable for far more sophisticated uses. In the future, we plan to add more white papers related to GRID to show how this technology can be used for a variety of additional tasks, such as surface analysis, diffusion modeling, zonal functions and more types of interpolations.&lt;/p&gt;

&lt;h3&gt;Downloads&lt;/h3&gt;

&lt;ul style=&quot;list-style-type:none; margin-left:0; padding-left:0;&quot;&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:9px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/download/GridDemo.zip&quot; style=&quot;padding-left:20px; background:url(/portals/1/icons/icon_download_2.gif) no-repeat left center;&quot;&gt;&lt;b&gt;Download GRID Demo Application&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none;&quot;&gt;&lt;b&gt;Note: You will need to download the &lt;a href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot;&gt;Map Suite Desktop .NET GIS Control Free Evaluation&lt;/a&gt; in order to run the example in this article.&lt;/b&gt; (Registration Required)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Have Questions?&lt;/h3&gt;

&lt;p&gt;Do you have any questions or comments about this article?  If so, feel free post your questions on the &lt;a href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/Default.aspx&quot;&gt;Map Suite Discussion Forums&lt;/a&gt; or leave feedback at the &lt;a href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/afv/topicsview/aff/16/Default.aspx&quot;&gt;ThinkGeo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Additional Resources&lt;/h3&gt;

&lt;ul style=&quot;list-style-type:none; margin-left:0; padding-left:0;&quot;&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/QuickStartGuides/tabid/197/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite QuickStart Guides&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/APIDocumentation/tabid/194/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite API Documentation&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/FAQs/tabid/196/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite FAQs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;About the Author&lt;/h3&gt;

&lt;p&gt;Val Guillou is a GIS analyst and developer at ThinkGeo, a software company specializing in geospatial software with an emphasis on software development tools and GPS tracking solutions.&lt;/p&gt;</description>
			<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4784/afv/topic/Default.aspx</link>
			<dc:creator>ThinkGeo</dc:creator>
			<pubDate>Thu, 13 Nov 2008 05:38:13 GMT</pubDate>
			<guid>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4784/afv/topic/Default.aspx</guid>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>Implementing a Custom Zoom Bar with Map Suite</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;When working with customers, many times I am asked, &quot;How do I implement a custom zoom bar into my application?&quot; At first glance this may seem like a difficult task, but with a little explanation on a few concepts and some sample code, you can easily implement a full-featured zoom bar that meets the needs of your application. In this article I will show you how to build a custom zoom bar using the prebuilt zoom levels defined within Map Suite Web Edition; however, the same concepts apply to building a custom zoom bar using the Map Suite Desktop Edition as well.&lt;/p&gt;&lt;/div&gt;

&lt;h3&gt;Zoom Levels Explained&lt;/h3&gt;

&lt;p&gt;The Map Suite Desktop, Web and Engine products each come with eighteen prebuilt zoom levels to handle the most common zooming scenarios, ranging from worldwide coverage down to local streets.  Having these prebuilt zoom levels at your disposal gives you complete control over how the map is rendered at each zoom level.  For example, if you have a map of the world, you wouldn't want to show a lot of detail like country names or roads when the map is zoomed completely out.  But as you zoom in, typically you would want to turn on more information such as labels and other map features.   With Map Suite you can do just that &amp;#8212; from tailoring ZoomLevel18 for views that show the entire globe, down to customizing ZoomLevel01 for a very detailed zoom area like local streets or small land parcels.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; Map Suite also allows you to specify your own zoom levels if the prebuilt levels don't meet your needs.&lt;/p&gt;

&lt;h3&gt;Getting Started&lt;/h3&gt;

&lt;p&gt;Now that we have covered how zoom levels work, let's get to the fun part: building our sample application with a custom zoom bar.  To get started, you will need to create a new ASP.NET web application in Visual Studio 2005. Next, you will need to reference the &lt;a href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteWeb/tabid/148/Default.aspx&quot;&gt;Map Suite Web Edition .NET Control&lt;/a&gt; and drag it on to the web page. Also, don't forget to add the HTTP Handler section to your Web.config file so the map control can render properly.&lt;/p&gt;

&lt;p&gt;Now let's add some code to the Page_Load event to initialize the Map and load up our layer representing all the countries in the world.  Additionally, we will write some code to color these countries in a reddish hue and turn on country name labeling for zoom levels one to fourteen.&lt;/p&gt;

&lt;h5&gt;Page_Load Code:&lt;/h5&gt;

&lt;code lang=&quot;csharp&quot;&gt;if (!IsPostBack)
	{
		// Set property of map control
		Map1.MapUnit = MapLengthUnits.DecimalDegrees;
		Map1.Mode = Map.ModeType.Pan;
		Rectangle Rect = new Rectangle(0, 0, (int)Map1.Width.Value, (int)Map1.Height.Value);
		Map1.CanvasGeoBrush = new GeoLinearGradientBrush(Rect, GeoColor.GeographicColors.Ocean1, GeoColor.GeographicColors.Ocean2, GeoLinearGradientMode.ForwardDiagonal);
		Map1.AjaxEnabled = true;
		
		// Load world countries layer
		Layer cntryLayer = new Layer(this.Server.MapPath(&quot;&quot;) + @&quot;\SampleData\world\cntry02.shp&quot;, true);
		//Color Countries with labels for all zoom level 14 and below
		cntryLayer.ZoomLevel01.GeoStyle = GeoAreaStyles.GetHueFamilyStyle(6, GeoColor.KnownColors.Red, GeoColor.KnownColors.Gray);
		cntryLayer.ZoomLevel01.GeoTextStyle = GeoTextStyles.Country1(&quot;CNTRY_NAME&quot;);
		cntryLayer.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.ZoomLevel14;
		//Color Countries with no labels to higest zoom levels
		cntryLayer.ZoomLevel14.GeoStyle = GeoAreaStyles.GetHueFamilyStyle(6, GeoColor.KnownColors.Red, GeoColor.KnownColors.Gray);
		cntryLayer.ZoomLevel14.ApplyUntilZoomLevel = ApplyUntilZoomLevel.ZoomLevel18;
		Map1.Layers.Add(cntryLayer);
		
		// Save some values in session
		Session.Add(&quot;FullScale&quot;, Map1.CurrentScale);
	}
&lt;/code&gt;

&lt;p&gt;Once you have this code implemented, you should be able to run your project and have a map displaying similar to the one below.&lt;/p&gt;

&lt;p&gt;&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/ZoomBar01.jpg&quot; alt=&quot;Sample Application Screenshot&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999;&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;HTML Code&lt;/h3&gt;

&lt;p&gt;Now that we have a simple map displaying, it's time to take it to the next step and create our custom zoom bar using standard HTML.  To do this, we will create a rather large zoom bar which has a button for each of the eighteen prebuilt zoom levels within Map Suite.  If eighteen zoom levels seem like too many, remember that you have complete control over the number of zoom levels and you can implement the number that makes sense for your application.  Below is the HTML that you'll need in order to implement a zoom bar with all eighteen levels. As you will notice, for each Zoom Button we make an AJAX call and pass in the level that each button represents.  Once you have the HTML implemented, the next step is to add the server side code to zoom the map in to the proper level.&lt;/p&gt;

&lt;h5&gt;HTML Code:&lt;/h5&gt;

&lt;code lang=&quot;html&quot;&gt;&lt;!-- Zoom Bar --&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level1&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel1','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt; Local
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level2&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel2','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level3&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel3','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level4&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel4','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level5&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel5','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level6&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel6','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt; City
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level7&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel7','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level8&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel8','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level9&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel9','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level10&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel10','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt; Area
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level11&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel11','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level12&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel12','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level13&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel13','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level14&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel14','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt; Country
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level15&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel15','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level16&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel16','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level17&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel17','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt;
&lt;/p&gt;
&lt;p class=&quot;ZoomButton&quot;&gt;
	&lt;img id=&quot;Level18&quot; src=&quot;images/zoom.gif&quot; width=&quot;25px&quot; height=&quot;12px&quot; alt=&quot;&quot; onclick=&quot;javascript:AjaxEvent('ClickLevel18','Map1');&quot; class=&quot;imgbtn&quot; style=&quot;cursor: hand&quot; /&gt; World
&lt;/p&gt;
&lt;/code&gt;

&lt;h3&gt;Server Side Code&lt;/h3&gt;

&lt;p&gt;With the zoom bar now implemented in the webpage, it's time to write some server side code to capture the AJAX event and zoom the map in to the proper level.  To handle the AJAX event raised from the JavaScript click event on the zoom bar button, we need to implement the Map's AjaxPostback event, write a case statement based on the argument from each zoom bar button and set the map zoom level accordingly.  Below is some sample code showing how to implement this functionality.&lt;/p&gt;

&lt;h5&gt;Map1_AjaxPostback Code:&lt;/h5&gt;

&lt;code lang=&quot;csharp&quot;&gt;protected void Map1_AjaxPostback(object sender, AjaxPostbackEventArgs e)
	{
		switch (e.EventName)
		{
			case &quot;ClickLevel1&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel01);
				break;
			case &quot;ClickLevel2&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel02);
				break;
			case &quot;ClickLevel3&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel03);
				break;
			case &quot;ClickLevel4&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel04);
				break;
			case &quot;ClickLevel5&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel05);
				break;
			case &quot;ClickLevel6&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel06);
				break;
			case &quot;ClickLevel7&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel07);
				break;
			case &quot;ClickLevel8&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel08);
				break;
			case &quot;ClickLevel9&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel09);
				break;
			case &quot;ClickLevel10&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel10);
				break;
			case &quot;ClickLevel11&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel11);
				break;
			case &quot;ClickLevel12&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel12);
				break;
			case &quot;ClickLevel13&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel13);
				break;
			case &quot;ClickLevel14&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel14);
				break;
			case &quot;ClickLevel15&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel15);
				break;
			case &quot;ClickLevel16&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel16);
				break;
			case &quot;ClickLevel17&quot;:
				Map1.CurrentScale = GetScaleFromZoomlevel(Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel17);
				break;
			case &quot;ClickLevel18&quot;:
				Map1.CurrentScale = (Double)Session&amp;#91;&quot;FullScale&quot;&amp;#93;;
				break;
			case &quot;ZoomIn&quot;:
				Map1.ZoomIn(20);
				break;
			case &quot;ZoomOut&quot;:
				Map1.ZoomOut(20);
				break;
			case &quot;TrackZoom&quot;:
				Map1.Mode = Map.ModeType.TrackZoomIn;
				break;
			case &quot;PreviousExtent&quot;:
				Map1.GetPreviousExtent();
				break;
			case &quot;ToggleExtent&quot;:
				Map1.ToggleMapExtents();
				break;
			case &quot;FullExtent&quot;:
				Map1.CurrentExtent = Map1.Layers&amp;#91;0&amp;#93;.Extent;
				break;
			case &quot;PanLeft&quot;:
				Map1.Pan(PanDirection.Left, 20);
				break;
			case &quot;PanRight&quot;:
				Map1.Pan(PanDirection.Right, 20);
				break;
			case &quot;PanUp&quot;:
				Map1.Pan(PanDirection.Up, 20);
				break;
			case &quot;PanDown&quot;:
				Map1.Pan(PanDirection.Down, 20);
				break;
			case &quot;PanNorthEast&quot;:
				Map1.Pan(45, 20);
				break;
			case &quot;PanNorthWest&quot;:
				Map1.Pan(315, 20);
				break;
			case &quot;PanSouthEast&quot;:
				Map1.Pan(135, 20);
				break;
			case &quot;PanSouthWest&quot;:
				Map1.Pan(225, 20);
				break;
			// Click zoom level button in zoom bar
			default:
				break;
		}
	
		// Sent value back and we will deal with it in client by &quot;CustomCallback&quot; function
		Map1.AjaxReturnArgs = &quot;Level&quot; + GetLevelNumber(Map1.CurrentScale).ToString();
	}
&lt;/code&gt;

&lt;p&gt;As you can see from the code above, for each click level we are calling a function named GetScaleFromZoomLevel and passing in the associated zoom level.  This function returns the new zoom level by calculating the midpoint of the zoom level's scale.  Once the new scale is calculated, all that remains is to set this scale to the Map's Current Scale property.  The code for the GetScaleFromZoomLevel function that returns the zoom level's midpoint is shown below for your reference.&lt;/p&gt;

&lt;code lang=&quot;csharp&quot;&gt;private double GetScaleFromZoomlevel(PresetZoomLevel presetZoomLevel)
{
	return (presetZoomLevel.UpperExtent + resetZoomLevel.LowerExtent) / 2;
}
&lt;/code&gt;

&lt;p&gt;Now the only thing left to do is return the zoom level that we are currently at, so that the zoom bar buttons can be updated accordingly.  This is accomplished by utilizing the GetLevelNumber function and the Map's AjaxReturnArgs property. In case you're not familiar with the AjaxReturnArgs property, it s a mechanism for passing data back to the client code.  At the end of the Map1_AjaxPostback event handler you will see the following line of code, which sets the AjaxReturnArgs property to the Zoom Level we are currently displaying:&lt;/p&gt;

&lt;code lang=&quot;csharp&quot;&gt;Map1.AjaxReturnArgs = &quot;Level&quot; + GetLevelNumber(Map1.CurrentScale).ToString();&lt;/code&gt;

&lt;p&gt;In case you were curious what the GetLevelNumber function does, it takes the CurrentScale of the map, compares it against all of the zoom levels and returns the current zoom level.  The code for this function is provided below for your reference.&lt;/p&gt;

&lt;h5&gt;GetLevelNumber Function Code:&lt;/h5&gt;

&lt;code lang=&quot;csharp&quot;&gt;public int GetLevelNumber(double scale)
	{
		int result;
		if (scale &lt; 0)
		{
			throw new Exception(&quot;The Width of your Map should be more than 0&quot;);
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel01.UpperExtent)
		{
			result = 1;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel02.UpperExtent)
		{
			result = 2;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel03.UpperExtent)
		{
			result = 3;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel04.UpperExtent)
		{
			result = 4;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel05.UpperExtent)
		{
			result = 5;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel06.UpperExtent)
		{
			result = 6;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel07.UpperExtent)
		{
			result = 7;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel08.UpperExtent)
		{
			result = 8;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel09.UpperExtent)
		{
			result = 9;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel10.UpperExtent)
		{
			result = 10;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel11.UpperExtent)
		{
			result = 11;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel12.UpperExtent)
		{
			result = 12;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel13.UpperExtent)
		{
			result = 13;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel14.UpperExtent)
		{
			result = 14;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel15.UpperExtent)
		{
			result = 15;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel16.UpperExtent)
		{
			result = 16;
		}
		else if (scale &lt; Map1.Layers&amp;#91;0&amp;#93;.ZoomLevel17.UpperExtent)
		{
			result = 17;
		}
		else
		{
			result = 18;
		}
		return result;
	}
&lt;/code&gt;

&lt;h3&gt;Client Side JavaScript Code&lt;/h3&gt;

&lt;p&gt;Now that the server side code is completed and the map is zoomed into the proper level, the next step is to update the zoom bar button images to identify which zoom level is currently being displayed on the map.  To accomplish this, we will need to implement the CustomCallback JavaScript function on the client side.  This will allow us to analyze the return arguments from the server side code and update each zoom bar button image accordingly.  For an example on how to implement this, please see the code below:&lt;/p&gt;

&lt;h5&gt;CustomCallback Javascript Code:&lt;/h5&gt;

&lt;code lang=&quot;script&quot;&gt;&lt;!--Get value from server and set the status of zoom button--&gt;
	&lt;script type=&quot;text/javascript&quot;&gt;
		function CustomCallback(ajaxReturnArgs)
		{
			if(ajaxReturnArgs != '')
			{
				var ImageButton;
				ImageButton = document.getElementById('Level1');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level2');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level3');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level4');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level5');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level6');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level7');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level8');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level9');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level10');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level11');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level12');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level13');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level14');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level15');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level16');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level17');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById('Level18');
				ImageButton.src='./images/zoombar_off.png';
				
				ImageButton = document.getElementById(ajaxReturnArgs);
				ImageButton.src='./images/zoombar_on.png';
			}
		}
	&lt;/script&gt;
&lt;/code&gt;

&lt;p&gt;Once you have this JavaScript function implemented, the appropriate zoom bar button should be highlighted in green, like the &quot;Country&quot; zoom bar button is in the screen shot below.&lt;/p&gt;

&lt;p&gt;&lt;IMG src=&quot;http://gis.thinkgeo.com/portals/1/articles/ZoomBar02.jpg&quot; alt=&quot;Sample Application Screenshot&quot; class=&quot;Figure&quot; style=&quot;border:1px solid #999;&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;In conclusion, you now can see how to build your own custom zoom bar to meet your specific needs.   Having this flexibility allows you to control the zoom levels, zoom bar location and overall look of the zoom bar implementation.  This can be very important when making the mapping screen easy to use for end users.  Below, I have listed several links where you can download the full source code and project to get more familiar with the sample application described in this article.  Finally, if you have any questions or suggestions please feel to post comments on the ThinkGeo Blog or Discussion Forums, as these are both great ways for us to hear from the Map Suite community.&lt;/p&gt;

&lt;h3&gt;Downloads &amp;amp; Online Demo&lt;/h3&gt;

&lt;ul style=&quot;list-style-type:none; margin-left:0; padding-left:0;&quot;&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://onlinedemos.thinkgeo.com/zoombardemo/&quot; target=&quot;_blank&quot;&gt;Zoom Bar Online Demo&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://onlinedemos.thinkgeo.com/zoombardemo/zoombardemo.zip&quot;&gt;Download Project and Source Code for Map Suite Zoom Bar Example&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite Web ASP.NET Control&lt;/a&gt; (Registration Required)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; You will need to download and install the Map Suite Web Edition in order to run the example in this article.&lt;/p&gt;

&lt;h3&gt;Have Questions?&lt;/h3&gt;

&lt;p&gt;Do you have any questions or comments about this article?  If so, feel free post your questions on the &lt;a href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/Default.aspx&quot;&gt;Map Suite Discussion Forums&lt;/a&gt; or leave feedback at the &lt;a href=&quot;http://blog.thinkgeo.com&quot; target=&quot;_blank&quot;&gt;ThinkGeo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Additional Resources&lt;/h3&gt;

&lt;ul style=&quot;list-style-type:none; margin-left:0; padding-left:0;&quot;&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/QuickStartGuides/tabid/197/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite QuickStart Guides&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/APIDocumentation/tabid/194/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite API Documentation&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/FAQs/tabid/196/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite FAQs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;About the Author&lt;/h3&gt;

&lt;p&gt;Clint Batman is co-founder and President of ThinkGeo, a software company specializing in geospatial software with an emphasis on software development tools and GPS tracking solutions.&lt;/p&gt;</description>
			<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4779/afv/topic/Default.aspx</link>
			<dc:creator>ThinkGeo</dc:creator>
			<pubDate>Wed, 12 Nov 2008 08:43:28 GMT</pubDate>
			<guid>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4779/afv/topic/Default.aspx</guid>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>Using Map Suite Explorer to Help You Build GIS Apps</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;Map Suite Explorer is a free tool that is included with each Map Suite Desktop, Web, and Engine .NET GIS component. It transforms the Map Suite API into an easy-to-use, user-friendly format that allows for ShapeFile viewing and rendering experimentation without the hassle of writing code. This article will show you how you can use Map Suite Explorer to help you write your GIS applications.                                       &lt;/p&gt;&lt;/div&gt;

&lt;h3&gt;Introduction&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/tabid/125/Default.aspx&quot;&gt;Map Suite GIS software&lt;/a&gt; has many powerful features, from reprojection and spatial queries to ShapeFile editing and customized labelers.  While these features allow a developer the ultimate in control, they can also deter developers with limited Map Suite experience from learning the basics about the Map Suite API.&lt;/p&gt;

&lt;p&gt;As a support representative, I see many questions about creating renderers, loading layers, and creating thresholds.  To assist with these questions, I sometimes reference Map Suite Explorer as a resource for this information.&lt;/p&gt;

&lt;h3&gt;What is Map Suite Explorer?&lt;/h3&gt;

&lt;p&gt;Map Suite Explorer is a free tool that is included with both the evaluation and full versions of each &lt;a href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/tabid/125/Default.aspx&quot;&gt;Map Suite Desktop, Web, and Engine .NET GIS component&lt;/a&gt;.  It is not a .NET mapping control; rather, it transforms the Map Suite API into an easy-to-use, user-friendly format that allows for ShapeFile viewing and rendering experimentation without the hassle of writing code.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Note!&lt;/b&gt; You will still need to use the &lt;a href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteDesktop/tabid/137/Default.aspx&quot;&gt;Desktop&lt;/a&gt;, &lt;a href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteWeb/tabid/148/Default.aspx&quot;&gt;Web&lt;/a&gt; or &lt;a href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteEngine/tabid/153/Default.aspx&quot;&gt;Engine&lt;/a&gt; controls to render a map your application. Map Suite Explorer itself is an application and uses the Map Suite control to render maps.&lt;/p&gt;

&lt;h3&gt;How is Map Suite Explorer Going to Help Me?&lt;/h3&gt;

&lt;p&gt;One example is that rather than writing out the code to load a layer, apply a threshold and a renderer, you can instead use Map Suite Explorer's GUI interface to complete this task in seconds.&lt;/p&gt;

&lt;p&gt;To begin, you will need to either &lt;a href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot;&gt;download an evaluation edition&lt;/a&gt; or &lt;a href=&quot;https://onlinestore.thinkgeo.com/onlinestore/Step1.aspx?onlinestoreid=b17ef9e4-c118-4246-8e80-39b6e49f4ab6&quot; target=&quot;_blank&quot;&gt;purchase a full version&lt;/a&gt; of the Map Suite Desktop, Web, or Engine .NET GIS components. (You may need to register on our site to download an evaluation.)&lt;/p&gt;

&lt;p&gt;After installing Map Suite, navigate to Start-&gt;Programs-&gt;ThinkGeo and chose the folder of your product. Next, click on &lt;b&gt;Map Suite Explorer&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Let's start by loading a Layer (ShapeFile) and adding a Threshold and a SymbolRenderer.&lt;/p&gt;

&lt;p&gt;First, we load the layer by clicking File-&gt;Add New Layer, or clicking the button named &quot;Add New Layer&quot; on the far left of the toolbar.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_01.png&quot; alt=&quot;Adding a new layer&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here I have selected the &lt;tt&gt;STATES.SHP&lt;/tt&gt; file from the &lt;tt&gt;C:\Program Files\ThinkGeo\Map Suite Desktop Edition 2.0\SampleData\USA&lt;/tt&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_02.png&quot; alt=&quot;Selecting STATES.SHP&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Click Open and immediately you will see the STATES layer displayed on the map.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_03.png&quot; alt=&quot;The STATES layer on the map&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you need to review several ShapeFiles quickly, you can easily add additional Layers using the same method, or by right-clicking on the &lt;b&gt;Layers&lt;/b&gt; node in the tree view.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_04.png&quot; alt=&quot;Right-clicking on the Layers node&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Right-clicking on the nodes will bring up menus where you can add many different elements to the map. Now that we have a Layer, let's render it in a different color.  Map Suite Explorer will automatically assign a color to a Layer unless there is a Threshold set, which is why a SymbolRenderer did not need to be specified right away.&lt;/p&gt;

&lt;p&gt;By right-clicking on the &lt;b&gt;Thresholds&lt;/b&gt; node, you will have the option to &lt;b&gt;Add a Threshold&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Note this relationship: You &lt;b&gt;add&lt;/b&gt; a &lt;b&gt;Threshold&lt;/b&gt; to the &lt;b&gt;STATES Layer&lt;/b&gt;. In code this would be: &lt;code&gt;Layer.Thresholds.Add(name of threshold)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_05.png&quot; alt=&quot;Adding a threshold&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a threshold, our map is blank. This is because we have only defined &lt;b&gt;&lt;i&gt;when&lt;/i&gt;&lt;/b&gt; we want a Layer to be displayed.  We now need to define &lt;b&gt;&lt;i&gt;how&lt;/i&gt;&lt;/b&gt; we want the Layer displayed.&lt;/p&gt;

&lt;p&gt;To do this, right-click on &lt;b&gt;SymbolRenderers&lt;/b&gt; for &lt;b&gt;NewThreshold1&lt;/b&gt; and select &lt;b&gt;Add a SymbolRenderer&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_06.png&quot; alt=&quot;Adding a SymbolRenderer&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We now need to define &lt;b&gt;&lt;i&gt;what&lt;/i&gt;&lt;/b&gt; symbol we want to be displayed by the SymbolRenderer. Right-click on the &lt;b&gt;Symbols&lt;/b&gt; node.  For the STATES ShapeFile, we'll choose &lt;b&gt;Add AreaSymbol&lt;/b&gt; since our ShapeFile contains area shapes.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_07.png&quot; alt=&quot;Adding an AreaSymbol&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Immediately you should see the outline of the states show up.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_08.png&quot; alt=&quot;The outline of the states on your map view&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By changing the &lt;b&gt;Pen&lt;/b&gt; and &lt;b&gt;Brush&lt;/b&gt; settings, we can control &lt;b&gt;&lt;i&gt;how&lt;/i&gt;&lt;/b&gt; the layer is rendered.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_09.png&quot; alt=&quot;The map view using a blue pen and red brush&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;Okay, Now We Can Change the Colors of the Map, But Other Than the Simple Relationships Demonstrated by the Tree, How Will This Help Me Code?&lt;/h3&gt;

&lt;p&gt;Map Suite has a feature to create either C#, VB.NET, or XML code that you can use to create your feasibility demos for management, or to see how the code is structured.&lt;/p&gt;

&lt;p&gt;By right-clicking on the &lt;b&gt;Map1&lt;/b&gt; node, you get the option to:&lt;/p&gt;

&lt;ul style=&quot;font-weight:bold;&quot;&gt;
	&lt;li&gt;Generate VB Code&lt;/li&gt;
	&lt;li&gt;Generate C# Code&lt;/li&gt;
	&lt;li&gt;Generate XML&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, I chose &lt;b&gt;Generate VB Code&lt;/b&gt; and here is the result:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_10.png&quot; alt=&quot;VB code generated by Map Suite Explorer&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With a couple of minor changes to this code, you can have a working map very quickly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://gis.thinkgeo.com/portals/1/articles/MapSuiteExplorer_11.png&quot; alt=&quot;A map rendered by the VB code from Map Suite Explorer&quot; class=&quot;Figure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you may notice, the code is quite verbose as it sets every single properly of the Map, Layer, Threshold, and SymbolRenderer.  While I would not recommend using Map Suite Explorer to write your production code, it can be very helpful in understanding the structure of the Map Suite API.&lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;Through this introduction to Map Suite Explorer, we have learned to load and render layers as well as create code that can be helpful in building demo applications.  Additionally, Map Suite Explorer has shown it can display relationships between objects in the &lt;a href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/tabid/125/Default.aspx&quot;&gt;Map Suite .NET GIS components&lt;/a&gt;. Although this information is available in the documentation, Map Suite Explorer's visual representation of those relationships may prove to be more intuitive and helpful.&lt;/p&gt;

&lt;p&gt;Please see the downloadable code below that demonstrates how you could use Map Suite Explorer-created code to jump start your experience with Map Suite!&lt;/p&gt;

&lt;h3&gt;Downloads&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://onlinedemos.thinkgeo.com/MapsuiteExplorerIntroduction/ExplorerSample.zip&quot; class=&quot;lightbluearrow&quot;&gt;Map Suite Explorer Sample Code in VB.NET&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Have Questions?&lt;/h3&gt;

&lt;p&gt;Do you have questions or comments about this article?  Feel free post your questions on the &lt;a href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/Default.aspx&quot;&gt;Map Suite Discussion Forums&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Additional Resources&lt;/h3&gt;

&lt;ul style=&quot;list-style-type:none; margin-left:0; padding-left:0;&quot;&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/QuickStartGuides/tabid/197/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite QuickStart Guides&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none; padding-bottom:6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/APIDocumentation/tabid/194/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite API Documentation&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;list-style-type:none;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/FAQs/tabid/196/Default.aspx&quot; target=&quot;_blank&quot;&gt;Map Suite FAQs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;About the Author&lt;/h3&gt;

&lt;p&gt;Ryan Desemo is one of ThinkGeo's lead customer support representatives and a technological guru.&lt;/p&gt;</description>
			<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4778/afv/topic/Default.aspx</link>
			<dc:creator>ThinkGeo</dc:creator>
			<pubDate>Wed, 12 Nov 2008 08:32:20 GMT</pubDate>
			<guid>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4778/afv/topic/Default.aspx</guid>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>Building Scalable Mapping &amp; GIS Apps with Web Services</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;With the emergence of popular online mapping applications over the past few years, more businesses are seeing a need to build mapping and GIS (Geographic Information Systems) functionality into their own custom applications. While online services like Google Maps &amp;amp; Virtual Earth work well in some cases, many times programmers need more control over the map data, map rendering, GIS capabilities, security and overall architecture. In this article, I will show you how to build a scalable mapping application utilizing a web service and how to consume the web service from a client application.&lt;/p&gt;&lt;/div&gt;

&lt;h3&gt;Getting Started&lt;/h3&gt;

&lt;p&gt;Typically, when I get ready to build a new mapping application, I take a look at how the application will be used and try to break the map data into two separate categories:&lt;/p&gt;

&lt;ul&gt;
    &lt;li style=&quot;padding-bottom: 8px;&quot;&gt;&lt;b&gt;Base Map&lt;/b&gt; &amp;ndash; The base map is made up of the relatively static map data that you always want to show. Typically, these base maps are made up of common features like political boundaries, water features, roads and points of interest. For this example, I'm going to keep the base map very simple and just use an outline of the United States. If I wanted to use a more detailed base map, I would utilize one of the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/MapDatasetPluginsforNETDevelopers/tabid/128/Default.aspx&quot;&gt;Map Suite Data Plugins&lt;/a&gt; to take care of the map data and rendering logic.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Dynamic Map Data&lt;/b&gt; &amp;ndash; This type of map data changes frequently and will need to be updated regularly. Typically, this type of data is stored in a database that is updated by the application or other outside sources. In this example, I will again keep it simple and simulate plotting the location of two customers in the United States.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you have an idea of the two different types of map data we will be dealing with, we can get started building the web service that will serve up our base maps.&lt;/p&gt;

&lt;h3&gt;The Web Service&lt;/h3&gt;

&lt;p&gt;The main goal we need to accomplish with this web service is to provide a high performance, scalable way to render the base maps. These base maps will then be consumed by our sample application. Encapsulating the logic to render the base maps into a web service allows us several advantages. These include centralized map data storage, map data only being loaded into memory once for all users, and finally, you can easily scale web services with a load balancer if demand grows.&lt;/p&gt;

&lt;p&gt;To achieve maximum performance, we are going to utilize the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteEngine/tabid/153/Default.aspx&quot;&gt;Map Suite Engine Edition .NET component&lt;/a&gt;. This component will do the heavy lifting of rendering the map image that will be consumed by our sample application. To get started, you will need to create a new ASP.NET web service project in Visual Studio 2005. Once the new project is loaded, the first thing you will need to do is write the web service initialization code. To do this, you will need to add a &lt;tt&gt;Global.asax&lt;/tt&gt; file to your web service. The &lt;tt&gt;Global.asax&lt;/tt&gt; code below is where the MapEngine object is instantiated and the map data is loaded so it can be used for all web service requests.&lt;/p&gt;

&lt;h5&gt;Global.asax Code:&lt;/h5&gt;

&lt;code lang=&quot;csharp&quot;&gt;using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using MapSuite;

namespace MapWebServiceExample
{
	public class Global : System.Web.HttpApplication
	{
		protected void Application_Start(object sender, EventArgs e)
		{
			//Instantiate the MapEngine component
			MapEngine mapServer = new MapEngine();
			//Create the Layer Object that loads the data for the USA outline
			Layer stateLayer = new Layer(this.Server.MapPath(&quot;&quot;) + @&quot;\SampleData\STATES.shp&quot;);
			//Set the color of the states to use the State1 geostyle
			GeoStyle stateGeoStyle = GeoAreaStyles.GetSimpleAreaStyle
				(GeoColor.GeographicColors.State1, GeoColor.KnownColors.Black);
			stateLayer.ZoomLevel01.GeoStyle = stateGeoStyle;
			//Apply this color &amp; style to all zoom levels
			stateLayer.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.ZoomLevel18;
			//Add the state layer to the map
			mapServer.Layers.Add(stateLayer);
			//Store the map engine object to Application state
			Application.Add(&quot;mapServer&quot;, mapServer);
		}
		
		protected void Application_End(object sender, EventArgs e)
		{
			//Clear the application
			Application.Clear();
		}
	}
}
&lt;/code&gt;

&lt;p&gt;Now that we have written the code to initialize the web service, the next step is to create a WebMethod that our client application can call to retrieve the map image. To accomplish this, you will need to add a new web service page to your solution with an &lt;tt&gt;.asmx&lt;/tt&gt; extension.  For this example, I called the web service page &lt;tt&gt;MapService.asmx&lt;/tt&gt; and exposed one public WebMethod called GetMapImage. The GetMapImage method takes in a few parameters so we can create the proper map image for the consuming application. These parameters include:&lt;/p&gt;

&lt;ul style=&quot;list-style-type: none;&quot;&gt;
    &lt;li&gt;&lt;span style=&quot;width: 60px;&quot;&gt;&lt;tt&gt;uLX&lt;/tt&gt;&lt;/span&gt; &amp;ndash; upper left x coordinate of the map image requested&lt;/li&gt;
    &lt;li&gt;&lt;span style=&quot;width: 60px;&quot;&gt;&lt;tt&gt;uLY&lt;/tt&gt;&lt;/span&gt; &amp;ndash; upper left y coordinate of the map image requested&lt;/li&gt;
    &lt;li&gt;&lt;span style=&quot;width: 60px;&quot;&gt;&lt;tt&gt;lRX&lt;/tt&gt;&lt;/span&gt; &amp;ndash; lower right x coordinate of the map image requested&lt;/li&gt;
    &lt;li&gt;&lt;span style=&quot;width: 60px;&quot;&gt;&lt;tt&gt;lRY&lt;/tt&gt;&lt;/span&gt; &amp;ndash; lower right y coordinate of the map image requested&lt;/li&gt;
    &lt;li&gt;&lt;span style=&quot;width: 60px;&quot;&gt;&lt;tt&gt;height&lt;/tt&gt;&lt;/span&gt; &amp;ndash; height of image requested&lt;/li&gt;
    &lt;li&gt;&lt;span style=&quot;width: 60px;&quot;&gt;&lt;tt&gt;width&lt;/tt&gt;&lt;/span&gt; &amp;ndash; width of the image requested&lt;/li&gt;
    &lt;li&gt;&lt;span style=&quot;width: 60px;&quot;&gt;&lt;tt&gt;quality&lt;/tt&gt;&lt;/span&gt; &amp;ndash; quality of compressed image returned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these parameters, we can now create the specified map image in our web utilizing the map engine object that we initialized in the &lt;tt&gt;Global.asax&lt;/tt&gt; file.  To see how this is accomplished, refer to the code below:&lt;/p&gt;

&lt;h5&gt;MapService.asmx Code:&lt;/h5&gt;

&lt;code lang=&quot;csharp&quot;&gt;using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using MapSuite;
using MapSuite.Geometry;

namespace MapWebServiceExample
{
	/// &lt;summary&gt;
	/// Summary description for Service1
	/// &lt;/summary&gt;
	&amp;#91;WebService(Namespace = &quot;http://tempuri.org/&quot;)&amp;#93;
	&amp;#91;WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)&amp;#93;
	&amp;#91;ToolboxItem(false)&amp;#93;
	public class MapService : System.Web.Services.WebService
	{
	&amp;#91;WebMethod&amp;#93;
		public byte&amp;#91;&amp;#93; GetMapImage(double uLX, double uLY, double lRX, double lRY, int height, int width, short quality)
		{
			// Handle threading and retrieve the map engine
			System.Threading.Monitor.Enter(Application&amp;#91;&quot;mapServer&quot;&amp;#93;);
			MapEngine map1;
			map1 = Application&amp;#91;&quot;mapServer&quot;&amp;#93; as MapEngine;
			//Create the Rectangle for the Map Area we want to return using cooridnates
			RectangleR fullExtent = new RectangleR(new PointR(uLX, uLY), new PointR(lRX, lRY));
			//Create new map bitmap and retrieve graphics object from it.
			Bitmap bmp = new Bitmap(width, height);
			Graphics g = Graphics.FromImage(bmp);
			//Pass the graphic objects into the map engine to draw the image
			map1.GetMap(g, fullExtent, width, height, MapLengthUnits.DecimalDegrees, 0);
			//Dispose of graphic object and handle threading
			g.Dispose();
			System.Threading.Monitor.Exit(Application&amp;#91;&quot;mapServer&quot;&amp;#93;);
			
			//Create a new memory stream to hold the image
			MemoryStream MemoryStream = new MemoryStream();
			
			//Get codecs
			ImageCodecInfo&amp;#91;&amp;#93; icf = ImageCodecInfo.GetImageEncoders();
			EncoderParameters encps = new EncoderParameters(1);
			EncoderParameter encp = new EncoderParameter(Encoder.Quality, (long)quality);
			
			//Set quality and save the map to the memory stream
			encps.Param&amp;#91;0&amp;#93; = encp;
			bmp.Save(MemoryStream, icf&amp;#91;1&amp;#93;, encps);
			MemoryStream.Close();
			//stream the image back to the client
			return MemoryStream.ToArray();
		}
	}
}
&lt;/code&gt;

&lt;h3&gt;The Client Application&lt;/h3&gt;

&lt;p&gt;Now that we have the web service built, we move our focus onto the client application that will consume the web service and plot the customer locations. For this example, we are going to build a ASP.NET web application utilizing the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteWeb/tabid/148/Default.aspx&quot;&gt;Map Suite Web ASP.NET server control&lt;/a&gt;; however, the web service can be consumed just as easily in a desktop client application utilizing the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteDesktop/tabid/137/Default.aspx&quot;&gt;Map Suite Desktop .NET control&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get started, you will need to create a new ASP.NET web application in Visual Studio 2005. Next, you will need to reference the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteWeb/tabid/148/Default.aspx&quot;&gt;Map Suite Web Edition .NET Control&lt;/a&gt; and drag it on to the web page. Also, don't forget to add the HTTP Handler section to your &lt;tt&gt;Web.config&lt;/tt&gt; file so the map control can render properly. Finally, you will need to add a web reference to the web service that was created earlier.&lt;/p&gt;

&lt;p&gt;Once you have your application ready to start coding, you will need to put some code into the Page_Load event handler and the Map_BeforeLayerDraw event handler, along with some additional coding to display the customer points and handle zooming in and out. The Page_Load event handler code accomplishes a couple things. First, it sets the MapUnit property, which tells the map control which coordinate system to use. In this example, the coordinate system we will be working with is decimal degrees, also known as longitude &amp;amp; latitude coordinates. Next, we write some code to set the initial zoom level and default the map to pan mode. Finally, the last bit of code in the Page_Load calls the DisplayCustomerPoints function, which handles the task of displaying our dynamic customer points on the map.&lt;/p&gt;

&lt;p&gt;You may be asking yourself, where does the web service fit in? By writing some code in the Map_BeforeLayersDraw event handler, we will be able to call the web service and draw our base map of the United States on the map control. To do this, we must first instantiate the web service and call the GetMapImage web method. Once we receive the byte array from the web service that contains the map image, the final task is to draw the map image on the map control using the graphics object passed into the event handler.&lt;/p&gt;

&lt;p&gt;To make the application a little bit more user friendly, I have added &amp;ldquo;zoom in&amp;rdquo; and &amp;ldquo;zoom out&amp;rdquo; buttons to allow the user to zoom in and out. To see this code and all of the code mentioned above, please review the below:&lt;/p&gt;

&lt;h5&gt;Default.aspx Code:&lt;/h5&gt;

&lt;code lang=&quot;csharp&quot;&gt;using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Drawing;
using MapSuite;
using MapSuite.Geometry;

public partial class _Default : System.Web.UI.Page
{
	protected void Page_Load(object sender, EventArgs e)
	{
		if (!IsPostBack)
		{
			//Set our Map Unit so we can use longitude &amp; latitude coordinates
			Map1.MapUnit = MapSuite.Geometry.MapLengthUnits.DecimalDegrees;
			//Tell the map control that we are going to control the extent
			Map1.AutoFullExtent = false;
			//Default the zoom/extent to show the lower 48 states
			Map1.CurrentExtent = new RectangleR(-125, 55, -66, 18);
			//Set the default mode of the map to panning
			Map1.Mode = MapSuite.WebEdition.Map.ModeType.Pan;
			//Enable Ajax capabilites for the map control
			Map1.AjaxEnabled = true;
			//Call the function so we can plot our customer points
			DisplayCustomerPoints();
		}
	}

	protected void Map1_BeforeLayersDraw(System.Drawing.Graphics G)
	{
		//Insantiate the webservice
		localhost.MapService MapMaker = new localhost.MapService();
		//Call the GetMapImage WebMethod
		byte&amp;#91;&amp;#93; images = MapMaker.GetMapImage(Map1.CurrentExtent.UpperLeftPoint.X,
		 Map1.CurrentExtent.UpperLeftPoint.Y,
		 Map1.CurrentExtent.LowerRightPoint.X,
		 Map1.CurrentExtent.LowerRightPoint.Y,
		 Convert.ToInt32(Map1.Height.Value),
		 Convert.ToInt32(Map1.Width.Value),
		 -1);
		//Create a new Bitmap Object using the image stream
		MemoryStream MemoryStream = new MemoryStream(images);
		Bitmap NewImage = new Bitmap(MemoryStream);
		//Draw the image onto the map control
		G.DrawImageUnscaled(NewImage, 0, 0);
	}

	protected void DisplayCustomerPoints()
	{
		//Create a Dynamic Data Layer to hold our customers
		DynamicLayer customers = new DynamicLayer();

		//Create Customer Point for LA
		PointMapShape custLA = new PointMapShape(new PointShape(-118.24, 34.05));
		//Use a Graphic for the customer symbol
		PointSymbol symLA = new PointSymbol
			(new Bitmap(this.Server.MapPath(&quot;&quot;) + @&quot;\images\customer.png&quot;));
		custLA.ZoomLevel01.GeoStyle.SymbolRenderers.Add(new SymbolRenderer(symLA));
		//Label the customer icon
		custLA.ZoomLevel01.GeoTextStyle = GeoTextStyles.GetSimpleTextStyle
			(null, &quot;Arial&quot;, 9, GeoFontStyle.Bold, GeoColor.KnownColors.Black);
		//Apply to all zoom levels
		custLA.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.ZoomLevel18;
		//Name the Customer
		custLA.Name = &quot;LA Customer&quot;;
		//Add the customer to the Dynamic Data Layer
		customers.MapShapes.Add(custLA);
		
		//Create Customer Point for KC
		PointMapShape custKC = new PointMapShape(new PointShape(-94.62, 39.11));
		//Use a Graphic for the customer symbol
		PointSymbol symKC = new PointSymbol
			(new Bitmap(this.Server.MapPath(&quot;&quot;) + @&quot;\images\customermale.png&quot;));
		custKC.ZoomLevel01.GeoStyle.SymbolRenderers.Add(new SymbolRenderer(symKC));
		//Label the customer icon
		custKC.ZoomLevel01.GeoTextStyle = GeoTextStyles.GetSimpleTextStyle
			(null, &quot;Arial&quot;, 9, GeoFontStyle.Bold, GeoColor.KnownColors.Black);
		//Apply to all zoom levels
		custKC.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.ZoomLevel18;
		//Name the Customer
		custKC.Name = &quot;Kansas City Customer&quot;;
		//Add the customer to the Dynamic Data Layer
		customers.MapShapes.Add(custKC);
		
		//Add Dynamic Data Layer to Map Control
		Map1.DynamicLayers.Add(customers);
	}

	protected void btnZoomIn_Click(object sender, EventArgs e)
	{
		//Zoom the map in by 20%
		Map1.ZoomIn(20);
	}
	protected void btnZoomOut_Click(object sender, EventArgs e)
	{
		//Zoom the map out by 30%
		Map1.ZoomOut(30);
	}
}
&lt;/code&gt;

&lt;p&gt;Once you have all of this coding completed, you should be able to run your client application and get a result similar to the screen shot below:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;Sample Application Screenshot&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/ScalableMappingAppsSample.jpg&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;Leveraging web services can allow you to build extremely scalable mapping and GIS solutions.  By utilizing the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteEngine/tabid/153/Default.aspx&quot;&gt;Map Suite Engine .NET Component&lt;/a&gt; in the web service, you can centralize all of your base map generation and large map datasets. In addition, you can still enjoy the developer experience of using the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteWeb/tabid/148/Default.aspx&quot;&gt;Map Suite ASP.NET&lt;/a&gt; &amp;amp; &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/GISComponentsforNETDevelopers/MapSuiteDesktop/tabid/137/Default.aspx&quot;&gt;Desktop controls&lt;/a&gt; to handle all user interactions and display of dynamic map data, among other things. This article barely scratches the surface of what can be accomplished with mapping &amp;amp; GIS web services in conjunction with a rich user interface. The downloadable code can be used as a good starting point for building your own scalable .NET GIS mapping applications.&lt;/p&gt;

&lt;h3&gt;Downloads&lt;/h3&gt;

&lt;ul style=&quot;list-style-type: none; margin-left: 0pt; padding-left: 0pt;&quot;&gt;
    &lt;li style=&quot;list-style-type: none; padding-bottom: 6px;&quot;&gt;&lt;a href=&quot;http://gis.thinkgeo.com/download/MapWebServiceExample.zip&quot;&gt;Map Web Service &amp;amp; Client Example Code in C#&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;list-style-type: none;&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot;&gt;Map Suite Engine .NET Component &amp;amp; Web ASP.NET Control&lt;/a&gt; (Registration Required)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; You will need to download and install these Map Suite components in order to run the example in this article.&lt;/p&gt;

&lt;h3&gt;Have Questions?&lt;/h3&gt;

&lt;p&gt;Do you have questions or comments about this article?  Feel free post your questions on the &lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/Default.aspx&quot;&gt;Map Suite Discussion Forums&lt;/a&gt; or leave feedback at the &lt;a target=&quot;_blank&quot; href=&quot;http://blog.thinkgeo.com&quot;&gt;ThinkGeo Blog&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Additional Resources&lt;/h3&gt;

&lt;ul style=&quot;list-style-type: none; margin-left: 0pt; padding-left: 0pt;&quot;&gt;
    &lt;li style=&quot;list-style-type: none; padding-bottom: 6px;&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Support/QuickStartGuides/tabid/197/Default.aspx&quot;&gt;Map Suite QuickStart Guides&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;list-style-type: none; padding-bottom: 6px;&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Support/APIDocumentation/tabid/194/Default.aspx&quot;&gt;Map Suite API Documentation&lt;/a&gt;&lt;/li&gt;
    &lt;li style=&quot;list-style-type: none;&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Support/FAQs/tabid/196/Default.aspx&quot;&gt;Map Suite FAQs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;About the Author&lt;/h3&gt;

&lt;p&gt;Clint Batman is co-founder and President of ThinkGeo, a software company specializing in geospatial software with an emphasis on software development tools and GPS tracking solutions.&lt;/p&gt;</description>
			<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4766/afv/topic/Default.aspx</link>
			<dc:creator>ThinkGeo</dc:creator>
			<pubDate>Wed, 05 Nov 2008 10:52:37 GMT</pubDate>
			<guid>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4766/afv/topic/Default.aspx</guid>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>Implementing Geocode USA Into a SQL Stored Procedure</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;This article will show you how to implement Geocode USA within a managed stored procedure in SQL Server 2005. The simple procedure involves preparing your files, configuring your database environment, creating an assembly and then building your stored procedure from that assembly.                                                                                                                                         &lt;/p&gt;&lt;/div&gt;


&lt;p style=&quot;line-height: 1.4em;&quot;&gt;
	&lt;img height=&quot;16&quot; width=&quot;16&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/icon_sql.png&quot; style=&quot;margin-right: 3px; vertical-align: middle;&quot; alt=&quot;&quot; /&gt; &lt;a href=&quot;http://thinkgeo.com/Download/GeocodeCLR/GeocodeSample.zip&quot;&gt;Download Tutorial Materials&lt;/a&gt;&lt;br /&gt;
&lt;img height=&quot;16&quot; width=&quot;16&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/icon_vsproject.png&quot; style=&quot;margin-right: 3px; vertical-align: middle;&quot; alt=&quot;&quot; /&gt; &lt;a href=&quot;http://thinkgeo.com/Download/GeocodeCLR/Demo.zip&quot;&gt;Download Demo Application&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;Steps&lt;/h3&gt;

&lt;h4&gt;1. Prepare Files&lt;/h4&gt;

&lt;p&gt;Unzip the &lt;a href=&quot;http://thinkgeo.com/Download/GeocodeCLR/GeocodeSample.zip&quot;&gt;GeocodeSample.zip&lt;/a&gt; file to &lt;tt&gt;C:\GeocodeSample.&lt;/tt&gt; Please note that the included GeocodeUSA.dll is from the free evaluation edition of Geocode USA; if you are a licensed user of the full version, you will want to use your own copy of GeocodeUSA.dll instead.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;Contents of the GeocodeSample.zip file&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_01.png&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;2. Configure Database Environment&lt;/h4&gt;

&lt;p&gt;Open the SQL Server 2005 Surface Area Configuration tool and select the &lt;b&gt;Surface Area Configuration for Features&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;The SQL Server 2005 Surface Area Configuration tool&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_02.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Enable the &lt;b&gt;CLR Integration&lt;/b&gt; so that you can CREATE ASSEMBLY.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;How to enable CLR integration&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_03.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Open SQL Server Management Studio and create a new database. In this example we used: &lt;b&gt;GeocodeSample&lt;/b&gt;. (The Database Owner must be a SQL server account, not a domain account.)&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;Creating a new database&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_04.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once the database has been created, use the following SQL command to alter the database and set TRUSTWORTHY to ON, so that you can use UNSAFE PERMISSION SET.&lt;/p&gt;

&lt;code&gt;ALTER DATABASE GeocodeSample SET TRUSTWORTHY ON&lt;/code&gt;

&lt;p&gt;Create a new assembly and choose the SQLGeocodeUSA.dll from the &lt;b&gt;Path to Assembly&lt;/b&gt; file browser. Be sure to set the &lt;b&gt;Permission Set&lt;/b&gt; as &lt;b&gt;Unsafe&lt;/b&gt;.  Click OK.  Now you will see two assemblies: &lt;tt&gt;GeoCodeUSA&lt;/tt&gt; and &lt;tt&gt;SQLGeocodeUSA&lt;/tt&gt;. Double-check that the &lt;b&gt;Permission Set&lt;/b&gt; is set to &lt;b&gt;Unsafe&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;Creating a new assembly and setting the Permission Set to Unsafe&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_05.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now you can create a stored procedure from the assembly.  For example:&lt;/p&gt;

&lt;code&gt;CREATE PROCEDURE ReverseGeocode
	-- Set default value, idx files directory
	@GeocodeIdxFolder nvarchar(200)='C:\GeocodeIdx2006fe',
	@Longitude float = 0.0,
	@Latitude float = 0.0
AS
	EXTERNAL NAME
		SQLGeocodeUSA.SQLGeocodeUSAEngine.ReverseGeoCode
&lt;/code&gt;

&lt;p&gt;Then, you can use this procedure as common stored procedure:&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;EXECUTE &amp;#91;GeocodeSample&amp;#93;.&amp;#91;dbo&amp;#93;.&amp;#91;ReverseGeoCode&amp;#93;;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Longitude = -95.2808458305725,&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Latitude = 38.9553176794061&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;Which gives you these results:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;Results of the above SQL query&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_06.png&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;3. Instantly Configuring the Database Environment&lt;/h4&gt;

&lt;p&gt;First, start SQL Server Management Studio.  Open the GeocodeSample.sql file, then execute the SQL statement.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;Executing the GeocodeSample.sql statement&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_07.png&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;4. Client Demonstration&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;http://thinkgeo.com/Download/GeocodeCLR/Demo.zip&quot;&gt;Demonstration code&lt;/a&gt; is also provided. The SQLGeocodeUSA project is a class library project, which acts as a bridge between the Geocode USA core and SQL Server 2005. You can use the SQLGeocodeClientDemo to demonstrate how to call the stored procedure in client code.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;border: 1px solid rgb(153, 153, 153);&quot; class=&quot;Figure&quot; alt=&quot;The GeocodeSample demo application&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/GeocodeCLR_08.png&quot; /&gt;&lt;/p&gt;</description>
			<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4765/afv/topic/Default.aspx</link>
			<dc:creator>ThinkGeo</dc:creator>
			<pubDate>Wed, 05 Nov 2008 10:40:17 GMT</pubDate>
			<guid>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4765/afv/topic/Default.aspx</guid>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>Building Thematic Maps Using Class Break Renderers and Map Suite</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;In Map Suite, the SymbolClassBreakRenderer class allows for multiple symbols to be defined that correlate to ranges or class breaks.  For example, you can use class breaks to produce a map that visually shows different population sizes. You can use this powerful feature to render your maps based on many types of differing values -- this article will show you the way.                                                                    &lt;/p&gt;&lt;/div&gt;


&lt;h3&gt;Introduction&lt;/h3&gt;

&lt;p&gt;If you need to build thematic maps (maps that provide information on a specific themes such as spatial distribution of population, timber volumes, weather, vegetation etc.) you can do so quickly and easily using the SymbolClassBreakRenderer Class in Map Suite. This article will show you the basics of getting started on your way to building your own feature rich mapping and spatial applications.&lt;/p&gt;

&lt;p&gt;(NOTE: This article references the ClassBreakRendererApp that is available in the sample applications with both the trial and full versions of Map Suite. This article also focuses on the Winforms Edition of Map Suite but most of the concepts and all of the example code applies for the Webforms (ASP.NET) Edition as well.)&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot;&gt;Register and download the trial version&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Opening the Sample Applications in Visual Studio.NET Solution&lt;/h3&gt;

&lt;p&gt;After you have downloaded and installed the full or trial version of Map Suite, you may want to look through the sample applications and source code that are included with the installation. You can view the samples by going to the START menu...All Programs...ThinkGeo...&amp;#91;YOUR MAP SUITE VERSION&amp;#93; and choose either the VB Sample Apps Source Code or C# Sample Apps Source Code menu item. This will open a solution in Visual Studio.NET that includes all of the Map Suite Sample applications as well as the source code. You may also need to add the Map Suite Map Control to your Toolbox in the Visual Studio.NET IDE. You can do this by using the Add/Remove Items feature and browsing to the winformsedition.DLL file that resides in the installation directory of Map Suite (By default this is C:\Program Files\ThinkGeo\&amp;#91;The Version You Have Installed&amp;#93;\).&lt;/p&gt;

&lt;p&gt;Now let's take a look at the SymbolClassBreakRenderer Class and how to use it.&lt;/p&gt;

&lt;h3&gt;Overview of the SymbolClassBreakRenderer Class&lt;/h3&gt;

&lt;p&gt;The SymbolClassBreakRenderer Class has the purpose of providing information to Map Suite in helping it determine when and how a portion of the map should be rendered based on a set of ranges or minimum and maximum values. The SymbolClassBreakRenderer is made up of two items: 1) The name of the column in the DBF that will provide the values for our class breaks and 2) a SymbolClassBreakCollection of SymbolClassBreakRenderers.ClassBreaks. For example, in the ClassBreakRendererApp sample application included with Map Suite there are several SymbolClassBreakRenderers.ClassBreaks added to a SymbolClassBreakCollection that define how the percentages of the Hispanic population within each Census tract of Travis County, Texas should be represented in terms of being rendered on the map.&lt;/p&gt;

&lt;p&gt;Let's take a look at some sample code so that this is clearer. Our first step is to set up the map by setting the MapUnit property to the proper value, loading a Layer from a Shape File (&lt;tt&gt;.shp&lt;/tt&gt;), setting the ThresholdUnit property on the Layer and creating a new Threshold that we can add our SymbolClassBreakRenderer to:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;'-- Set length units for shape files
Map1.MapUnit = MapSuite.Geometry.MapLengthUnits.DecimalDegrees

Dim Layer As New Layer(&quot;C:\Program Files\ThinkGeo\YOUR MAPSUITE VERSION\sampledata\usa\austin\austintracts.shp&quot;)

'-- Set layer's length units to miles because that is what we want to work with
Layer.ThresholdUnit = ThresholdUnits.miles

'-- Only show this layer when map is zoomed in showing less than 10,000
'-- miles across
Dim Threshold As New Threshold(10000, 0)
&lt;/code&gt;

&lt;p&gt;For a more detailed explanation of the above code, shape data and DBF files, see the Map Suite Quick Start User's Guide.&lt;/p&gt;

&lt;p&gt;Now that we have our Map, Layer and Threshold defined we can start building our SymbolClassBreakRenderer.ClassBreaks that will define how we want the map to display the percentages. To do this we will be defining a SymbolClassBreakCollection as mentioned earlier and adding SymbolClassBreakRenderer.ClassBreaks to it. In the example we want to use the below defined ranges:&lt;/p&gt;

  &lt;table width=&quot;300&quot; cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; border=&quot;1&quot; style=&quot;margin-bottom:18px;&quot;&gt;
     &lt;tr&gt;
         &lt;th width=&quot;105&quot;&gt;&lt;b&gt;Percentage (%)&lt;/b&gt;&lt;/th&gt;
         &lt;th&gt;&lt;b&gt;Display As&lt;/b&gt;&lt;/th&gt;
     &lt;/tr&gt;
     &lt;tr&gt;
         &lt;td width=&quot;105&quot;&gt;Less than 15&lt;/td&gt;
         &lt;td&gt;Light Goldenrod Yellow&lt;/td&gt;
     &lt;/tr&gt;
     &lt;tr&gt;
         &lt;td width=&quot;105&quot;&gt;15 - 30&lt;/td&gt;
         &lt;td&gt;Light Green&lt;/td&gt;
     &lt;/tr&gt;
     &lt;tr&gt;
         &lt;td width=&quot;105&quot;&gt;30 - 45&lt;/td&gt;
         &lt;td&gt;Lime Green&lt;/td&gt;
     &lt;/tr&gt;
     &lt;tr&gt;
         &lt;td width=&quot;105&quot;&gt;45 - 59&lt;/td&gt;
         &lt;td&gt;Green&lt;/td&gt;
     &lt;/tr&gt;
     &lt;tr&gt;
         &lt;td width=&quot;105&quot;&gt;More than 60&lt;/td&gt;
         &lt;td&gt;Dark Green&lt;/td&gt;
     &lt;/tr&gt;
  &lt;/table&gt;

&lt;p&gt;Now that we know what we need to define for our class breaks, let's look at the code for accomplishing this. Note that we also introduce a new Class called the SymbolClassBreakRenderer.ClassBreakCap. It is explained further in the comments of the code and below:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;'-- Define our SymbolClassBreakCollection to hold our class breaks
Dim ClassBreaks As New SymbolClassBreakCollection

'-- First break is 'below 15%'
ClassBreaks.Add(New SymbolClassBreakRenderer.ClassBreak(15, New AreaSymbol(New Pen(Color.Black), New SolidBrush(Color.LightGoldenrodYellow))))

'-- Next break is 'below 30%'
ClassBreaks.Add(New SymbolClassBreakRenderer.ClassBreak(30, New AreaSymbol(New Pen(Color.Black), New SolidBrush(Color.LightGreen))))

'-- Next break is 'below 45%'
ClassBreaks.Add(New SymbolClassBreakRenderer.ClassBreak(45, New AreaSymbol(New Pen(Color.Black), New SolidBrush(Color.LimeGreen))))

'-- Every class break needs a cap. With a cap of 60, here, we are saying
'-- that everything below the cap, or 'below 60%' (which means 45% or
'-- above but below 60%)should be displayed one way and those over the cap
'-- ('60% or above') should be displayed another way.
Dim ClassBreakCap As New SymbolClassBreakRenderer.ClassBreakCap(60, New AreaSymbol(New Pen(Color.Black), New SolidBrush(Color.DarkGreen)), New AreaSymbol(New Pen(Color.Black), New SolidBrush(Color.Green)))

'-- Add the ClassBreakCap to the SymbolClassBreakCollection
ClassBreaks.Add(ClassBreakCap)
&lt;/code&gt;

&lt;p&gt;Note that each constructor for a SymbolClassBreakRenderer.ClassBreak takes an argument of type Double as a maximum value (all values that fall below the value should be rendered) and a SymbolRenderer. The SymbolClassBreakRenderer.ClassBreakCap Class takes break value that puts a sort of end or &amp;quot;topper&amp;quot; on the class breaks by defining how to render values that fall in the range below the value and the last defined SymbolClassBreakRenderer.ClassBreak as well as the value and anything above. In the last line of code we add the SymbolClassBreakRenderer.ClassBreakCap to the SymbolClassBreakCollection.&lt;/p&gt;

&lt;p&gt;Note, for more information on the SymbolRenderer Class, see the &lt;a href=&quot;http://gis.thinkgeo.com/Support/QuickStartGuides/tabid/197/Default.aspx&quot;&gt;Map Suite QuickStart Guides&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Using the SymbolClassBreakRenderer Class&lt;/h3&gt;

&lt;p&gt;Now we can finally use the SymbolClassBreakRenderer Class by defining what column we will use from the DBF (.dbf) file that is associate with our Shape Date File (.shp). In this case, the column we want to use is 'perchisp01'. This will give us our percentages. If we provide that along with the SymbolClassBreakCollection of our class breaks, Map Suite will automatically render each area appropriately. Below is the code for doing this:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;'-- Add layer and class break render to map so it can be displayed
Dim ClassBreakRenderer As New SymbolClassBreakRenderer(&quot;perchisp01&quot;, ClassBreaks)

Threshold.SymbolRenderers.Add(ClassBreakRenderer)

Layer.Thresholds.Add(Threshold)

Map1.Layers.Add(Layer)

'-- Force map to redraw completely
Map1.Refresh()
&lt;/code&gt;

&lt;p&gt;In the above code we simply create the new SymbolClassBreakRenderer as described earlier, add it to the SymbolRenderer Collection of the Threshold, add the Threshold to the Layer, and the Layer to the Map. Our last step is to call the Refresh() method of the map so that it can redraw it completely. When we run this code in the ClassBreakRenderersApp sample application, it renders like this:&lt;/p&gt;

&lt;p&gt;&lt;img height=&quot;463&quot; width=&quot;550&quot; border=&quot;0&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/ClassBreakRenderer.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it is very easy to use SymbolClassBreakRenderers in your Map Suite application. With only a few lines of code, and some representative data, you can have professional looking thematic analysis maps to your users in very little time. Remember to check out the ClassBreakRenderersApp sample application to see this code and other features such as traversing the map with operations like Zooming, Panning, Track Zoom etc. as well as SymbolDisplayer class used for creating legends like the one shown on left side of the image above.&lt;/p&gt;

&lt;h3&gt;Other Resources&lt;/h3&gt;

&lt;p&gt;There are several other resources at ThinkGeo to help you get started to developing feature rich mapping and spatial applications for Microsoft .NET. Some of those resources are listed below. You can always reach a ThinkGeo support representative by phone toll-free at (866) 847-7510 or via email at &lt;a href=&quot;mailto:support@thinkgeo.com&quot;&gt;support@thinkgeo.com&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Sample Applications&lt;/h3&gt;

&lt;p&gt;There are 35+ sample applications included with Map Suite when you download the trail version that include the source code to show you how to do various operations using the Map Suite component. It is very beneficial to go through those examples and the code. Both VB.NET and C# are included.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://onlinedemos.thinkgeo.com/sampleapps/&quot;&gt;View the Map Suite sample applications online&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Discussion Forums&lt;/h3&gt;

&lt;p&gt;The Map Suite Discussion Forums are a great place to get answers to all of your Map Suite development questions. The ThinkGeo Support Team monitors the forums daily and can help you on your way to being successful with Map Suite.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/Default.aspx&quot;&gt;Visit the Discussion Forums online&lt;/a&gt;&lt;/p&gt;</description>
			<link>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4764/afv/topic/Default.aspx</link>
			<dc:creator>ThinkGeo</dc:creator>
			<pubDate>Wed, 05 Nov 2008 10:29:15 GMT</pubDate>
			<guid>http://gis.thinkgeo.com/Support/DiscussionForums/tabid/143/aff/18/aft/4764/afv/topic/Default.aspx</guid>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>Using the Spatial Query Capabilities of Map Suite</title>
			<description>&lt;div style=&quot;width:750px; background: #e0eaf0 url(/portals/1/in_this_article.jpg) no-repeat left top; margin-bottom:20px; padding:45px 15px 20px 15px;&quot;&gt;&lt;p style=&quot;margin:0; font-size:12px; color:#333;&quot;&gt;Map Suite has powerful spatial querying abilities. This allows you to find features of a Layer based on spatial criteria such as containment, intersection etc. This capability is built into the API of Map Suite and is easy even for the non-GIS developer to use. This article will introduce these concepts and show you how they can be accomplished with Map Suite.                                                                    &lt;/p&gt;&lt;/div&gt;

&lt;h3&gt;Introduction&lt;/h3&gt;

&lt;p&gt;If you need to build spatial querying capabilities into your maps you can do so quickly and easily using the spatial querying capabilities built into Map Suite. This article will show you the basics of getting started on your way to building your own feature rich spatial applications.&lt;/p&gt;

&lt;p&gt;(NOTE: This article references the SpatialQueriesApp that is available in the sample applications with both the trial and full versions of Map Suite. This article also focuses on the Winforms Edition of Map Suite but most of the concepts and all of the example code applies for the Webforms (ASP.NET) Edition as well.)&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://gis.thinkgeo.com/Products/MapSuiteFreeTrialDownloads/tabid/152/Default.aspx&quot;&gt;Register and download the trial version&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Opening the Sample Applications in Visual Studio.NET Solution&lt;/h3&gt;

&lt;p&gt;After you have downloaded and installed the full or trial version of Map Suite, you may want to look through the sample applications and source code that are included with the installation. You can view the samples by going to the START menu...All Programs...ThinkGeo...&amp;#91;YOUR MAP SUITE VERSION&amp;#93; and choose either the VB Sample Apps Source Code or C# Sample Apps Source Code menu item. This will open a solution in Visual Studio.NET that includes all of the Map Suite Sample applications as well as the source code. You may also need to add the Map Suite Map Control to your Toolbox in the Visual Studio.NET IDE. You can do this by using the Add/Remove Items feature and browsing to the winformsedition.DLL file that resides in the installation directory of Map Suite (By default this is C:\Program Files\ThinkGeo\&amp;#91;The Version You Have Installed&amp;#93;\).&lt;/p&gt;

&lt;p&gt;Now let's take a look at spatial queries in Map Suite.&lt;/p&gt;

&lt;p&gt;(NOTE: This article assumes the basics of loading Shape Files into Map Suite Layers. For a more detailed explanation of how to load Layers and how Map Suite uses shape data and DBF files, see the &lt;a href=&quot;http://gis.thinkgeo.com/Support/QuickStartGuides/tabid/197/Default.aspx&quot;&gt;Map Suite Quick Start User's Guides&lt;/a&gt;.)&lt;/p&gt;

&lt;h3&gt;Why Spatial Queries?&lt;/h3&gt;

&lt;p&gt;You might be wondering why you would want to use spatial queries. Some good examples of spatial querying might be the need to know the coverage area for a Wi-Fi system or the proximity of possible hazardous materials to schools so that plans can be made accordingly. These are just a couple of examples of how spatial querying can be a powerful tool.&lt;/p&gt;
&lt;p&gt;So let's jump right into an example using Map Suite and see how you can get started adding these features to your own applications.&lt;/p&gt;

&lt;h3&gt;Setting the Map Mode to a Track Shape&lt;/h3&gt;

&lt;p&gt;The first step in spatial querying is to allow for our user to create a shape that will be used for querying, for example using a rectangle or an ellipse. We can accomplish this by using the Mode property of the Map and one of several mode types from the ModeType Enumeration:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Map1.Mode = ModeType.TrackLine
Map1.Mode = ModeType.TrackPolygon
Map1.Mode = ModeType.TrackRectangle
Map1.Mode = ModeType.TrackCircle
Map1.Mode = ModeType.TrackEllipse
&lt;/code&gt;

&lt;p&gt;Any one of these values will change the cursor to the mode of selection indicated and allow the user to draw a shape. We now need to be able to create the shape based on what was drawn and we can do this using Map Suite's FinishedTrackShape() Event which takes an argument of type BaseShape. Example code from the SpatialQueriesApp sample application is shown below:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private Sub Map1_FinishedTrackShape(ByVal Shape As MapSuite.Geometry.BaseShape) Handles Map1.FinishedTrackShape
	If Not Shape Is Nothing Then
		'-- After a shape is drawn, store the shape and re-run the query
		mQueryBaseShape = Shape
		Call SpatialQuery()
	End If
End Sub
&lt;/code&gt;

&lt;p&gt;The above code captures the BaseShape being passed in and assigns it to the mQueryBaseShape variable which is defined at the Class level as a BaseShape. Immediately after the SpatialQuery() method is called. Let's take a look at that method to get an idea of how Map Suite can now query the data:&lt;/p&gt;

&lt;code lang=&quot;vb&quot;&gt;Private Sub SpatialQuery()
	Dim RecordNumbers() As Integer
	Dim lyr As Layer
	Dim Index As Integer
	'-- Here we want to deselect everything on each layer
	For Each lyr In Map1.Layers
		lyr.Deselects()
	Next
	'-- Identify which layer with which to work
	If RadioButtonCounties.Checked Then
		Index = 0
	ElseIf RadioButtonRoads.Checked Then
		Index = 1
	ElseIf RadioButtonCities.Checked Then
		Index = 2
	End If
	lyr = Map1.Layers.Item(Index)
	'-- Get the record numbers returned by the query
	RecordNumbers = lyr.SpatialQuery(mQueryBaseShape, CType
	(ComboBoxSpatialRules.SelectedIndex, SpatialQueryContainment))
	'-- Select the returned items on the layer - this will highlight the
	'-- features so the user can see the query results
	lyr.Selects(RecordNumbers)
	'-- Redraw the map
	Map1.Refresh()
End Sub
&lt;/code&gt;

&lt;p&gt;There are several things occurring in the above code so let's take a look at each step in detail. We first declare an array of type Integer that will hold the record numbers returned from our query. We then declare an object of type Layer that will be used in an iteration to deselect anything that might have been set to selected in a previous query. We then declare an Index of type Integer which will be set when we determine from the user interface which Layer the user wants to query (see user interface of the SpatialQueriesApp in the sample applications).&lt;/p&gt;

&lt;p&gt;Now that we have our variables declared we want to go ahead and iterate through all available Layers in the map and deselect anything that might be selected as mentioned above. We then check the user interface RadioButtons to see which one the user has selected. In the case of our SpatialQueriesApp sample application, it is either the Counties, Roads or Cities Layer. After we set the appropriate index, we can now get a reference to that Layer in the Map's Layer collection.&lt;/p&gt;

&lt;p&gt;Now comes the magic. With just a simple call to the referenced Layer's SpatialQuery() method, passing in the previously populated BaseShape (mQueryBaseShape) set in the Map's FinishedTrackShape() method and a value from the SpatialQueryContainment Enumeration (NOTE: In the above code, the value is coming from a user interface ComboBox control and then it is cast specifically to type SpatialQueryContainment), an array of record numbers (Integers) is returned. You can then call the Layer's Selects() method and pass in the array. Lastly, we call the Refresh() method on the map.  When we do, the appropriate items on the map that resulted from the query will be automatically highlighted, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;img width=&quot;550&quot; border=&quot;0&quot; src=&quot;http://gis.thinkgeo.com/portals/1/articles/SpatialQuery1.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3&gt;The SpatialQueryContainment Enumeration&lt;/h3&gt;

&lt;p&gt;Let's take a closer look at the SpatialQueryContainment Enumeration. This provides what type of query operation needs to be performed on the selected Layer features to be queried:&lt;/p&gt;

  &lt;table width=&quot;100%&quot; cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; border=&quot;1&quot;&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;th width=&quot;118&quot;&gt;&lt;b&gt;Operation&lt;/b&gt;&lt;/th&gt;
              &lt;th&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/th&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td width=&quot;118&quot;&gt;Contained&lt;/td&gt;
              &lt;td&gt;Returns the features that fully contain the querying shape.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td width=&quot;118&quot;&gt;Containing&lt;/td&gt;
              &lt;td&gt;Returns the features that the querying shape fully or partially contains.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td width=&quot;118&quot;&gt;Fully Containing&lt;/td&gt;
              &lt;td&gt;Returns the features that the querying shape fully contains.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td width=&quot;118&quot;&gt;Containing Centroid&lt;/td&gt;
              &lt;td&gt;Returns the features whose centroid is contained by the querying shape.&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td width=&quot;118&quot;&gt;Fully Outside&lt;/td&gt;
              &lt;td&gt;Returns the features that are fully outside the querying shape.&lt;/td&g