World Mapper (1)

February 15th, 2007

One of the objectives of this website is to create our own mapping applications. This requires a strong knowledge base of geography, mathematics, and computer programming. So before we can jump into the more advanced projects, we have to start with the basics. We’ve already been investigating GPS in our previous posts but today we will create a very basic mapping application.

Our “World Mapper” program begins by acquiring a map of the earth. I downloaded this one from Wikipedia Commons and shrunk it down to 400 pixels by 200 pixels.

WorldMap

The simplest way to map the Earth is to treat longitude and latitude as X/Y points. This approach is not a true geographic projection but it is the easiest to comprehend. Thus, the valid X ranges are -180 to 180 and the Y ranges are -90 to 90.

LatLongMap

Our program will plot the locations of points on the world map as entered by the user. Nothing fancy here – this is just setting the stage for some upcoming projects.

Create a new C# Windows Application in Visual C# Express. Add a PictureBox from the toolbox and set it’s image location to the world map. Then add 2 labels, 2 textboxes, and 2 buttons to create some thing like this:
WorldMapper1

There are only 4 functions we need to add to make the program work so the first to write is the “Map It” button’s click event. Double-click on the button to enter code view. Here is the approach I used:

 

private void btnMapLocation_Click(object sender, EventArgs e)
{
  double longX = 0;
  double latY = 0;
  try
  {
    longX = Convert.ToDouble(txtLongitude.Text);
    latY = Convert.ToDouble(txtLatitude.Text);
  }
  catch
  {
    MessageBox.Show("Invalid numbers!");
  }
  if ((longX > 180) || (longX < -180))
    MessageBox.Show("Longitude out of range!");
  else if ((latY > 90) || (latY < -90))
    MessageBox.Show("Latitude out of range!");
  else
  {
    Point mapPoint = ConvertLatLon2ImagePosition(longX, latY);
    PlotPosition(mapPoint);
  }
}

 

We first validate the user’s input by checking for numbers and then for out of range errors. Next we do 2 things: 1) convert the lat/long location to actual on-screen pixel coordinates and 2) use a small bitmap to display the location of the form.

When I created the form, I named the Picture Box of the world “picWorldMap” so…

 

private Point ConvertLatLon2ImagePosition(double longX, double latY)
{
  Point imgPos = new Point();
  imgPos.X = (int)(((longX + 180) / 360) * picWorldMap.Width);
  imgPos.Y = (int)(((90 - latY) / 180) * picWorldMap.Height);
  imgPos.X += picWorldMap.Location.X;
  imgPos.Y += picWorldMap.Location.Y;
  return imgPos;
}

 

Take a minute to review the math here. It’s not to complex but is somewhat tricky. We need to first find where within the map the point should go. Then we adjust the location by adding the picture box’s position within the form itself. This results an a X/Y location (measured from the top-left corner) that is based on the entire form and will plot correctly within the map itself.

To show each point on the map, I create a 4×4 bitmap(WorldMapperPoint )to serve as the point’s symbol. I then needed a function to show the point on the map. To be spatially accurate, you must modify the point’s position based on the bitmap size. Since the image was 4×4, I subtracted 2 from the position to ensure the point is centered over the location.

 

private void PlotPosition(Point mapPoint)
{
  PictureBox p = new PictureBox();
  p.Name = "mappoint";
  p.ImageLocation = "point.bmp";
  p.Location = new Point(mapPoint.X - 2, mapPoint.Y - 2);
  p.Size = new Size(4,4);
  frmMain.ActiveForm.Controls.Add(p);
  p.BringToFront();
}

 

I also added a button to clear the points from the map.

 

private void btnClearMap_Click(object sender, EventArgs e)
{
  Form currentForm = frmMain.ActiveForm;
  Control[] mappoints = currentForm.Controls.Find("mappoint", true);
  for (int i = 0; i <= mappoints.GetUpperBound(0); i++)
  {
    currentForm.Controls.Remove(mappoints[i]);
  }
}

 

The application should compile and run successfully. There is a lot of functionality that could be added but for now we’ve accomplished our objective.

Continue to part 2