October 26, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Web Service Secrets

  • June 16, 2003
  • By Karl Moore
  • Send Email »
  • More Articles »

View the Real World in Your Application, with TerraServer

The Statue of Liberty. Yankee Stadium. The Pentagon. Hoover Dam. Unrelated? I think not. You see, they're all listed in TerraServer, the mass Microsoft-supported Web service that allows you to view the world and all (or at least most/some) of its famous sights from the skies.

You can check out the Web version of this cool service at terraserver.microsoft.com—or you can use the power of Web services to plug straight into this functionality.

In this example, I'm going to show you how to connect into the service, then retrieve an image using its "popular name"—such as 'White House' or 'Statue of Liberty.' You can do much more, certainly; however, this example will at least demonstrate some of the capabilities—and perhaps make you aware as to how troublesome the graphic 'crunching' code can get.

Ready to go? Launch Visual Studio .NET and create a new application. Select Project > Add Web Reference from the menu and type in the URL of the TerraServer description page>http://terraservice.net/TerraService.asmx>then press Return. Click the 'Add Reference' button when available.

Next, add an Imports statement to save us constantly referring to the net.terraservice namespace. If you're creating this in a Windows form project, you'll need to type something like the following just above the Public Class part of your form code:

Imports NameOfProject.net.terraservice

Now, we're ready to start writing code to use our service. Add the following method to your formclass (or class, or whatever):

Public Sub CreateBitmapFromPlaceName( _
    ByVal PlaceName As String, ByVal FileName As String)
    ' Size of image to create
    Const WIDTH As Integer = 600
    Const HEIGHT As Integer = 400
    ' Set up objects to use
    Dim objTheme As New Theme()
    Dim objScale As New Scale()
    Dim objTS As New TerraService()
    Dim objABB As AreaBoundingBox
    Dim imgImage As Image
    Dim objPF() As PlaceFacts
    Try
        ' Retrieve list of matching points
        objPF = objTS.GetPlaceList(PlaceName, 1, False)
        ' If no matches, exit
        If objPF.Length = 0 Then Exit Sub
        ' Settings - type of image and scale
        objTheme = Theme.Photo
        objScale = objScale.Scale2m
        ' Gets details of the final full image AreaBoundingBox
        objABB = objTS.GetAreaFromPt(objPF(0).Center, _
            objTheme, objScale, WIDTH, HEIGHT)
        ' Create objects to handle image in memory
        Dim objPFmt As System.Drawing.Imaging.PixelFormat = _
            System.Drawing.Imaging.PixelFormat.Format32bppRgb
        Dim imgTemp As Image = New Bitmap(WIDTH, HEIGHT, objPFmt)
        Dim objGraphics As Graphics = Graphics.FromImage(imgTemp)
        ' Create objects to store current locations
        Dim intStartX As Integer = objABB.NorthWest.TileMeta.Id.X
        Dim intStartY As Integer = objABB.NorthWest.TileMeta.Id.Y
        Dim x, y As Integer
        ' Cycle through the portions of our whole AreaBoundingBox,
        ' incrementally retrieving and stiching together our image
        For x = intStartX To objABB.NorthEast.TileMeta.Id.X
            For y = intStartY To objABB.SouthWest.TileMeta.Id.Y _
                    Step -1
                Dim objTID As TileId
                Dim imgTile As Image
                objTID = objABB.NorthWest.TileMeta.Id
                objTID.X = x
                objTID.Y = y
                imgTile = Image.FromStream(New System.IO. _
                                           MemoryStream ( _
                    objTS.GetTile(objTID)))
                objGraphics.DrawImage(imgTile, _
                    (x - intStartX) * imgTile.Width - _
                    objABB.NorthWest.Offset.XOffset, _
                    (intStartY - y) * imgTile.Height - _
                    objABB.NorthWest.Offset.YOffset, _
                    imgTile.Width, imgTile.Height)
            Next
        Next
        ' Finally, save to the passed filename
        imgTemp.Save(FileName, System.Drawing.Imaging. _
                     ImageFormat.Bmp)
    Catch
        Return
    End Try
End Sub

Well, this is a pretty hefty piece of code. Let me walk you through it. We begin by defining the dimensions of the width and height of the image you want, then declare a few objects we'll be using later on. Next, we retrieve a list of PlaceFacts objects, depending on the place name passed into the method, exiting if we have no matches. After that, we initialize a couple of settings—the type of image and the scale. Moving on, the next line takes a WIDTH by HEIGHT area around the center of the first matching PlaceFacts object, creating an AreaBoundingBox object—which essentially defines the area for your image.

Continuing, our code then creates various objects to handle our image, then begins one big loop. Starting at the upper left (northwest) point, it goes about chunk by chunk, retrieving an array of bytes from the Web service representing an image block (it has to move in this block format because the service only returns images to a maximum of 200 x 200 at any one time). As one loop moves across, collecting images, the second one moves down—and eventually the whole image is stitched together. Finally, our Graphic object is saved to the specified filename as a bitmap—ready to perhaps load into a control or stream through a Web page.

We can call this function a little like this:

CreateBitmapFromPlaceName("Statue of Liberty", "c:\myimage.bmp")

And that's it—one simple line of code, yes, but a disproportionate number of hours spent figuring how to make it work. However, that's still not all the TerraServer can do—it may be the most popular usage, but there's always more to discover. Did you know you can retrieve the population of an area you've mapped, for example—or convert a longitude and latitude value to the nearest place name on file?

Check out terraserver.microsoft.com and click the 'Web services' link for documentation and examples. Good luck and enjoy the service!

Spy on the Pentagon with the Terraserver Web service

Goodbye!

Well, that's a rap, folks!

You've been reading Karl Moore with the .NET secrets series. I do hope our paths meet again shortly. Don't forget to stop by www.karlmoore.com to read the latest, or drop me a personal note at karl@karlmoore.com.

Thanks again and bye for now!





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel