8b – Using Map Tiles

Well done, you’ve mapped your data, but wouldn’t it be nice if we could contextualize it with a background map.

This can be done in many ways but one option is to use an external library called Unfolding. Unfolding is a library that allows us to import map tiles (images that tile together to form a map) so that we can plot points on them. It handles mapping your longitude and latitudes to these maps in an accurate way (otherwise this is can be quite fiddly to align your plotted points accurately to an underlying image).

Download the library and install it by trying this simple tutorial – instructions here.

Once you have finished this tutorial and you have a map, check out the function from your code.

map = new UnfoldingMap(this);

This is where you are initialising (giving initial data) to your map object. This is also the function where you can select what you want your map tiles to look like. Because we are importing them from a database, we can change to different tiles to get different appearances.

We can do this by importing another part of the unfolding library:

import de.fhpotsdam.unfolding.providers.*;

And then by putting in a second argument to the UnfoldingMap function (in void setup()). This second argument chooses our tiles.

map = new UnfoldingMap(this, new StamenMapProvider.WaterColor());

Read the tutorial for more info on map types and switching between them.

Adding Map Tiles to your OpenPaths example

First import the unfolding libraries at the top of your code before void setup();

//import libraries
import de.fhpotsdam.unfolding.*;
import de.fhpotsdam.unfolding.geo.*;
import de.fhpotsdam.unfolding.utils.*;
 
//for map styles
import de.fhpotsdam.unfolding.providers.*;

You also need to declare your unfolding object. This is of course also done with your other variables before void setup(). Our object is called map.

//declare unfolding object
UnfoldingMap map;

In void setup, you then need to initialize this object and select the map tiles you want to use as explained before with the UnfoldingMap function:

map = new UnfoldingMap(this, new StamenMapProvider.WaterColor());

Unfolding relies heavily on a location class. The location class is basically a way of storing a longitude and latitude value together.

Here is the location class declared and initialised. This makes a new location object called nyLocation.

Location nyLocation = new Location(latitude, longitude);

If you ever need the specific x or y values from a location and can do so by calling:

float nyX = nyLocation.x; 
float nyY = nyLocation.y;

But you don’t need this right now.

Now we now want to set an area of interest for our map, so that we can zoom down on our location. You can do this by making a location object for NY called nyLocation in void setup() and initializing it as above with the coordinates of the city.

We do this by adding this line to void setup();

Location nyLocation = new Location(40.8f, -73.97f);

This zooms into the area of New York.

And then underneath it we call a function call zoomAndPan from the map object. The zoomAndPan function requires a location argument (where your map will start) and zoom distance (10 works for me).

map.zoomAndPanTo(nyLocation, 10);

See how this line of code is calling the zoomAndPan function that is from the map object. This should remind you of how you have set up classes.

Next up you need to set up some more code in void draw() so that our map tiles are synced with our location points.

First of all, as you have seen before, you need to draw the map tiles at the top of void draw with the map draw function. This will draw your tiles to the background for every loop of draw.

map.draw();

Then look at your for loop running through you data. At the moment it looks like this:

//use a for loop to y which we use to call each row number
  for (int y=0; y<table.getRowCount (); y++) {
    //to animate this data, change the getRowCount() to a counter
 
    //get latitude using getFloat(row, column) - from the first column
    float lat = table.getFloat(y, 0);
 
    //get longtitude using getFloat(row, column) - from the second column
    float lon = table.getFloat(y, 1);
 
    //remap coordinates to the dimensions of our screen
    lat=map(lat, 40.5, 41.5, 0, height);
    lon=map(lon, -73.5, -74.5, 0, width);
     //draw points
    fill(0, 0, 255);
    ellipse(lat, lon, 20, 20);
  }

We will be calling a class called screenPosition. This class will calculate the screen coordinates from the longitude and latitude values. Its basically replaces the map functions in the for loop above, it does the translation from longitude and latitude to screen values for us. The screenPosition class requires one argument which is a location object. So we need to pass it a location.

Thus we need to set up a location object for each loop of draw and pass it our lat and lon. And then use this location in the map.getScreenPosition function: We do this with this line:

//make a location object and give it our lat and lon values
    Location location= new Location(lat, lon);
    //pass the location to the posLocations object.
    ScreenPosition posLocations = map.getScreenPosition(location);

So this replaces the map functions and the for loop now looks like this:

  //use a for loop to y which we use to call each row number
  for (int y=0; y<table.getRowCount (); y++) {
    //to animate this data, change the getRowCount() to a counter
 
    //get latitude using getFloat(row, column) - from the first column
    float lat = table.getFloat(y, 0);
 
    //get longtitude using getFloat(row, column) - from the second column
    float lon = table.getFloat(y, 1);
 
    //make a location object and give it our lat and lon values
    Location location= new Location(lat, lon);
    //pass the location to the posLocations object.
    ScreenPosition posLocations = map.getScreenPosition(location);
    //    float m=map(n,0,384,0,255);
    fill(0, 0, 255, 100);
    noStroke();
    ellipse(posLocations.x, posLocations.y, 20, 20);
}

You should now have a map. If you want to be able to interact with the map by being able to scroll around on it you need to add the function:

MapUtils.createDefaultEventDispatcher(this, map);

This should go in void setup, right after where you initialise the map object. After this line:

map = new UnfoldingMap(this, new StamenMapProvider.WaterColor());

You can set a restriction on the amount that the screen will pan using the setPanningRestriction function. It requires a 2 arguments, a location object and a distance in kms. If you add this after the createDefaultEventDispatcher you will notice that your map panning is restricted.

map.setPanningRestriction(nyLocation, 30);

If you want to experiment with more functions enabling map interaction – see this tutorial:
http://unfoldingmaps.org/tutorials/interactions-simple.html

'+
1
'+
2 - 3
4 - 5
6 - 7
8 - 9
10 - 11
12 - 13
13 - 14
[x]