Creating a Bing Maps (Virtual Earth) backend with custom pushpins

by Alan S. 29. June 2010 02:10

Any web application using Bing Maps has to offer something specific to that site or program. For example, you might have a database of speed cameras for your city and want to offer your visitors a way to define search parameters and display the results with custom pushpin graphics.

 

Check out these reference books for Bing Maps, Google Earth, and Map Scripting:

 

The heart and soul of this functionality lies in a basic cross-platform Pushpin class that can be set up and populated using a C# backend, then passed to a JavaScript function that can read the generic data types in the class, parse them, and display the information.

   1: namespace App_Code
   2: {
   3:     public class Pushpin
   4:     {
   5:         private double latitude;
   6:         private double longitude;
   7:         private string title;
   8:         private string description;
   9:         private string imageUrl;
  10:  
  11:         public double Latitude
  12:         {
  13:             get { return latitude; }
  14:             set { this.latitude = value; }
  15:         }
  16:  
  17:         public double Longitude
  18:         {
  19:             get { return longitude; }
  20:             set { this.longitude = value; }
  21:         }
  22:  
  23:         public string Title
  24:         {
  25:             get { return title; }
  26:             set { this.title = value; }
  27:         }
  28:  
  29:         public string Description
  30:         {
  31:             get { return description; }
  32:             set { this.description = value; }
  33:         }
  34:  
  35:         public string ImageUrl
  36:         {
  37:             get { return imageUrl; }
  38:             set { this.imageUrl = value; }
  39:         }
  40:  
  41:         public Pushpin()
  42:         {
  43:             this.latitude = 0;
  44:             this.longitude = 0;
  45:             this.plancount = 0;
  46:             this.title = "";
  47:             this.description = "";
  48:             this.imageUrl = "";
  49:         }
  50:  
  51:         public Pushpin(double latitude, double longitude,
  52:             string title, string description, string imageUrl)
  53:         {
  54:             this.latitude = latitude;
  55:             this.longitude = longitude;
  56:             this.title = title;
  57:             this.description = description;
  58:             this.imageUrl = imageUrl;
  59:         }
  60:     }
  61: }

In the code above, we start by declaring a Namespace (App_Code). The Pushpin class has basic information like latitude, longitude, title, description, and an image URL (imageurl). Our C# backend will populate each of these values and return an array of Pushpin objects to the Javascript function our map page.

 

Next , we need to create a web service to accommodate our requests to populate the plot points of our speed camera locations. We create a SpeedCameraQueryService.asmx file that is empty except for providing an interface to our backend function:

   1: <%@ WebService Language="C#" CodeBehind="~/App_Code/SpeedCameraQueryService.cs" Class="SpeedCameraQueryService" %>
   2:  

And here is the corresponding SpeedCameraQueryService.cs file (placed in our App_Data directory).

   1: using App_Code;
   2: using System.Data;
   3:  
   4: [WebService]
   5: [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
   6: // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
   7: [ScriptService]
   8: public class SpeedCameraQueryService : WebService {
   9:  
  10:     [WebMethod]
  11:     public Pushpin[] GetAllInfo()
  12:     {
  13:         ArrayList ppArray = new ArrayList();
  14:         Pushpin pGeneric;
  15:         /* HERE IS WHERE YOU INSERT YOUR QUERY OR DATA READ */
  16:         /* When done, iterate thru your results... */
  17:         foreach (SpeedCamera.productRow r in MyDatatable)
  18:         {
  19:             pGeneric = new Pushpin( r.Lat,
  20:                 r.Long,
  21:                 r.Title,
  22:                 r.Description,
  23:                 "Images/plotpin2.png");
  24:             ppArray.Add(pGeneric);
  25:         }
  26:         Pushpin[] ia = (Pushpin[])ppArray.ToArray(typeof(Pushpin));
  27:         return ia;
  28:     }

Now, in our map.aspx file, we implement a Javascript function that is run when your users click a button on your webpage asking for the location of your speed cameras.

   1: var _PushpinLayer;
   2: _PushpinLayer = new VEShapeLayer();
   3: // our VEMap variable, map, gets the empty shape layer added
   4: // This line should go in your 'load' function that creates your map.
   5: map.AddShapeLayer(_PushpinLayer);
   6:  
   7: // Now we have the function that gets called when a user clicks
   8: // the button requesting to see our speed camera data.
   9: function PreviewPlots() {
  10:     var _totalRet = 0;
  11:     _PushpinLayer.DeleteAllShapes();
  12:     SpeedCameraQueryService.GetAllInfo(onGetComplete, onGetFailed);
  13:     function onGetComplete(result) {
  14:         PlotPreviewData(result);
  15:     }
  16:     function onGetFailed(result) {
  17:         alert("Error while connecting to the remote web service. Please try again later.");
  18:     }
  19: }
  20:  
  21: function PlotPreviewData(data) {
  22:     if (data == null)
  23:         return;
  24:     for (var i = 0; i < data.length; i++) {
  25:         var currPushpin = data[i];
  26:         var pushpinLocation = new VELatLong(currPushpin.Latitude, currPushpin.Longitude);
  27:         var shape = new VEShape(VEShapeType.Pushpin, pushpinLocation);
  28:         var customIconUrl = currPushpin.ImageUrl;
  29:         if (customIconUrl != "") {
  30:             shape.SetCustomIcon(customIconUrl);
  31:         }
  32:         shape.SetTitle(currPushpin.Title);
  33:         shape.SetDescription(currPushpin.Description);
  34:         _PushpinLayer.AddShape(shape);
  35:     }
  36: }

 

THE Definitive guide for Bing Maps! Now available on Amazon.com!

Click on the “Map Scripting 101” book at left to find out about this incredible book on map scripting covering Bing, Google, and Yahoo!

 

If you need assistance or have questions in setting up your application / web site to import KML files, please send us a message and we will schedule a call and let you know how we can help!

 


How to display KML / KMZ files using Bing Maps (Virtual Earth)

by Alan S. 24. June 2010 08:21

 

 

kmlupload I’ve waited and waited for months now for Microsoft to add the popular KML / KMZ file formats directly to their library, but have seen no indication from them that it is coming anytime soon. This is a big deal for sites or desktop applications that offer Bing Maps, but can’t find a way for their visitors to display KML files on their local machines on your map page. The closest thing is a method by which you place the KML file on a publicly accessible web server, then call a Bing Maps remote function (passing it the URL of the file to be converted) and then displaying the returned results.

 

We decided to make the most of a good thing and create a simple way to allow our customers to display their local KML files on our publicly accessible embedded Bing Maps websites and applications. Microsoft requires that the KML to be decoded be Internet accessible so they can get the file, decode it with their proprietary methods, and simply return the data as a series of VEShape objects.

 

To accomplish this, our map software has an “Import KML” button that brings up a file selection dialog. The user selects the file which calls a server side C# function:

   1: WebClient wcUp = new WebClient();
   2: byte[] responseArray = wcUp.UploadFile("http://myserver.com/uploadkmlfile.aspx", tbFilename.Text);
   3: WebHeaderCollection myWebHeaderCollection = wcUp.ResponseHeaders;
   4: // Now read the filename from our header response
   5: string sNewFilename = myWebHeaderCollection.Get(0);
   6: mapBrowser.Document.InvokeScript("LoadKMLMap", new object[] { "http://myserver.com/KML_Temp/" + sNewFilename});

In line 2, we pass the URL of an .aspx file that exists on our server that handles the upload. Line 5 is important because it sets the variable sNewFilename to the unique name given the file on our server. Here is the sample UploadKMLFile.aspx and corresponding code so you can see what is happening:

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="UploadKMLFile.aspx.cs" Inherits="UploadKMLFile" %>
   2: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   3: <html xmlns="http://www.w3.org/1999/xhtml">
   4: <head runat="server">
   5:     <title></title>
   6: </head>
   7: <body>
   8:     <form id="form1" runat="server">
   9:     <div>
  10:     </div>
  11:     </form>
  12: </body>
  13: </html>

As you can see, the .aspx code is just a dummy page that relies on the C# code-behind to handle the upload:

   1: using System.IO;
   2: using System.Net;
   3: using System.Web;
   4:  
   5: public partial class UploadKMLFile : System.Web.UI.Page
   6: {
   7:     protected void Page_Load(object sender, EventArgs e)
   8:     {
   9:         foreach(string f in Request.Files.AllKeys) 
  10:         {
  11:             string sNewName = string.Format("{0}{1}{2}{3}{4}.kml",
  12:                     DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);//file.FileName);
  13:             HttpPostedFile file = Request.Files[f];
  14:             file.SaveAs(Server.MapPath("~/KML_Temp/") + sNewName);
  15:             Response.Headers.Add("Newname", sNewName);
  16:         }
  17:     }
  18: }

The C# code behind (UploadKMLFile.aspx.cs) takes the file and saves it to a unique name in our ~/KML_Temp directory. We then add a response header which is the new name of the uploaded file. That name is then returned to the calling function on our map web page.

 

Line 6 of the first code block (server side C# function) then takes that returned new name and calls a JavaScript function on our map page called LoadKMLMap. That function looks like this:

   1: var lNew = new VEShapeLayer();
   2:  
   3: function LoadKMLMap(sFile)
   4: {
   5:     var veLayerSpec = new VEShapeSourceSpecification(VEDataType.ImportXML, sFile, lNew);
   6:     map.ImportShapeLayerData(veLayerSpec, onFeedLoad, true);
   7: }
   8:  
   9: function onFeedLoad(feed)
  10: {
  11:     var iCount=0;
  12:     for(var i=0;i<lNew.GetShapeCount();i++)
  13:     {
  14:         iCount++;
  15:         var shape = lNew.GetShapeByIndex(i);
  16:         if(shape.GetCustomIcon() == null) // we have no icon
  17:         {
  18:             shape.HideIcon();
  19:             shape.SetCustomIcon("<img src='http://upload.wikimedia.org/wikipedia/commons/c/ce/Transparent.gif' />");
  20:         }    
  21:     }
  22:     map.AttachEvent("onmouseover", ShapeInfo);
  23:     alert('KML collection loaded. There are '+ feed.GetShapeCount()+
  24:         ' items in this list. ' + iCount + ' actual');
  25: }
  26:  
  27: function ShapeInfo(e)
  28: {
  29:    if(e.elementID != null)
  30:    {
  31:       X = e.mapX;
  32:       Y = e.mapY;
  33:       var point = map.PixelToLatLong(new VEPixel(X,Y));
  34:       shape = map.GetShapeByID(e.elementID);
  35:       map.ShowInfoBox(shape, point);
  36:    }
  37: }

NOTES: Make sure to set the permissions on your KML_Upload directory so that IIS can write the stream to your server. The temporary filename given to each uploaded file ensures that the file is unique and that users looking at files of the same name on their machines will not have the same name on our server, thus avoiding conflict of files.

 

THE Definitive guide for Bing Maps! Now available on Amazon.com!

If you need assistance or have questions in setting up your application / web site to import KML files, please send us a message and we will schedule a call and let you know how we can help!

 


Internet Marketing: If you can’t beat ‘em, join ‘em

by Alan S. 20. June 2010 09:25

It seems the more tricks I learn about SEO (Search Engine Optimization), the more surprised I am at just how much time it takes to implement some of these strategies. All that time spent just to crawl a few steps up the first page of Google. In the last couple of months, I started thinking about what is the 'cut-off' point where I would simply spend money or time in order to boost rankings. It's something any good SEO marketer considers when tackling a new genre or niche, sort of like PPC.

 

torgogoogleIn this example, our company came out with a new product, Dr. Torgo's PC System Inventory. Actually, it's a program I wrote about 6 months ago that my cohort Steve took and finalized and has been bugging me to put it up for sale, which I eventually did. Anyway, when I put it up on the site I immediately went into SEO mode and started marketing the product as a direct link to our site. It took a couple of days until I finally noticed we were listed at around 7 or 8. I started wasting more and more time trying to up it a couple of notches. I then submitted it to a download site called SoftPedia. Within a couple of days, I was somewhat shocked to see that my new SoftPedia entry made it before my actual site page on page 1 of Google!

 

We tried the same thing with eMail Scraper. I got decent (page 3) listings direct to our site but could never crack the first page with "email scraper" as a keyword without a PPC campaign. But after submitting the download link to a couple of sites I found that they did the work for me:
scrapergoogle

 

So for next time, I'll simply post it to various software download libraries and get first ranking on certain keywords rather than bust my rear for hours trying to beat them. The download sometimes comes from their site, but I still handle all of the payments with no commission to them, so in this case... I couldn't beat 'em, so I'll join 'em!

 

A couple of notes:
1)
A Google search on "email scraper" yields about 1.5 MILLION results, so to be listed on page 1 (or 2) is no small task.
2) Believe it or not, Torgo (and all it's variations a-la MST3K, IMDB, etc.) is still an incredibly popular search word. Every time I run Google, Yahoo, or Bing stats it ranks among the top 10 search words to my site every time. I used to have a posting about Torgo and the redirects to that page were consistently high. So, even though they're looking for the movie version of Torgo, they'll still hit my site!


StarCraft II should be another Blizzard hit

by Alan S. 15. June 2010 03:55

250px-StarCraft_box_art OMG – Six more weeks until the most highly anticipated game (IMHO) hits the shelves, StarCraft II. When the original came out in 1998, it sold over 11 million copies. It came out at a bad time, the genre had been beaten to death for many years before with games like Masters of Orion and Command and Conquer. But this game offered something quite different. It had only three races and game play was superb. Add to that the voice acting talents of some Mystery Science Theater 3000 alumni and that game was ready to take off.

 

Now we find ourselves in 2010. To quote a famous Paul McCartney and Wings song, “You’d think that people would have had enough of silly top down viewers.” That’s what I would have thought. Being an old school gamer, I love top down view games. They’re a bit nostalgic but also familiar. The view is perfect for this and other types of games. Sometimes it’s done well and sometimes not so well (I’m talking to you, Civ 4). I’ve been playing the BETA and it seems that they focused on 3d control, not camera control. Take out the fancy camera controls and you’ve got smooth, brilliant 3d graphics that look and play great!

 

starcraft2

I’ve read on some other boards that people are complaining about he fact there are still only three races (protoss, terran, and zerg). IMHO, there should be no more than those three. Why? Well, have you ever played Warhammer 40k? There are so many army types, races, and variants that it drastically cuts into the game play time and also adds to the total confusion that could ensue when certain rules / abilities are challenged. Sometimes, you can have too much of a good thing. Any Games Workshop product is a testament to that. (Let the hate mail begin…)

 

The three races keeps it simple to understand and makes you a smarter player by understanding your enemy better. You’re head can be clogged with strategy and tactics rather than remembering complex and numerous one-off rules. To make up for only having three races, they have drastically expanded the types of units that each can produce, and some of the familiar units that return in StarCraft II will have new tricks up their sleeves, which will give the game its own unique flavor. In addition, Battle.net will be overhauled with some new and exciting features to enhance online play and competition, while the single-player campaign will also offer some unique aspects for players to enjoy.

 

StarCraft II will also be a fully featured multiplayer game, and all three races will be available for competitive play. However, the campaign expansions are race specific, so play a bit with all three races to find the one you want to advance with, then order the expansion specific to that race.

 

See you on BattleNet!


PC System Inventory released by eSource Development

by Steve W 10. June 2010 10:52

TorgoboxWell, it took a little pushing for Al to give his blessing, but Dr. Torgo’s PC System Inventory tool was finally released today! This tool is great for PC Technicians and IT Departments that need quick access to detailed system information to assist in troubleshooting, software inventory, and software licensing.

 

Dr. Torgo's PC System Inventory offers a full range of system query options and powerful reporting tools. This software quickly generates reports on several dozen hives of system information including disks, CPU, memory, motherboard, users, ports, services, software, and MORE.

 

Dr. Torgo's PC System Inventory is a detailed query tool that allows users to get information about their systems like never before. The depth of the search option trees is amazing, and the detailed listing of installed software is perfect for tracking your software license compliance. This software is so detailed, it's nearly impossible to list all of the query trees and options. High level tabs include:

 
  • Hardware
  • Storage
  • Memory
  • System
  • Network
  • Security
  • Development
  • Utility
  • Services
  • Software
    • It also offers an export feature that allows you to save your inventory results to a variety of formats including HTML, CSV, Plain Text, or TAB delimited. Click HERE to see a sample report

     

    only29 Don't pay hundreds of dollars for those "one-click" PC troubleshooters that give vague information on only the simplest of problems. Let Dr. Torgo's PC System Inventory show you information so detailed that researching things like driver version, software revisions, and BIOS revisions are a snap! We now offer a 3 day trial version which lets you try before you buy!

     

    NOTE: Torgo is a fictional character in the movie Manos: The Hands of Fate, played by John Reynolds. The quaver-voiced, maladroit satyr servant of "The Master", Torgo is charged with looking after the lodge while the Master is away. Torgo rose to pop culture notability following the Mystery Science Theater 3000 airing of Manos on January 30, 1993, following which he was featured on the television series as a recurring character. Now, the character is immortalized in eSource Development software.


    Taipan’s original BASIC source code found

    by Alan S. 7. June 2010 01:54

    TaipanBOX

    We released Taipan! for Windows a little over a year ago. Since then, we have received a few requests to provide people with the original BASIC source code for this game. So for those of you that want to take a trip down memory lane and see some old school BASIC programming, here is the source code for the original Taipan!

     

     

    Our version of the game is based off of the same logic patterns that are contained in the original code. There was some artistic license taken and some new features added (obviously) to make the game more appealing on a Windows platform rather than just a text based game. These include sound, graphics, and quests.

     

    I came across the code the other day while doing a server rebuild and decided to put it up as a quick link here. So for those of you nostalgia freaks that really want to see what that old BASIC code looked like, now is your chance. For you younger gamers / developers out there, take a look at the code and be amazed at how small it is. In those days, a game’s enjoyment was based on your imagination and not all of the visual and audio candy they pepper into games to make them playable. To me, games today are not as cerebral as they were in the old days, but the trade-off is that they look and sound much better.




    Recent Comments

    Comment RSS

    Month List

    Who's Watchin' Me?


    Brew Good Cheer with DIY Beer from MakeBeer.net!




    Barnes&Noble.com


    www.cellarswineclub.com