Tutorial: Building a Beautiful Map

Good maps tell stories. Most maps focus on how to get from A to B. In this tutorial, we'll show you how to use the Visual API to understand the nuances of places with rich context to aid in sophisticated decision making.

As part of this, you'll learn how to define layer specifications for rendering, which tell the Visual API what to render and how to render it.

The Task

You're going to build a house hunting research application. People don't know exactly where they want to live, but they know they care about schools, economics, transit, and environmental hazards of a place. We will build a map, step-by-step, that will help them find areas that meet their criteria.

EasyMap

To start, we take a shortcut: the EasyMap web service. With it, you avoid having to craft HTML or Javascript. That comes later. The examples will be overlain on a Bing Map, but they could easily overlay a number of others.

Layer Style Specifications

A layer is one set of geometries drawn in a particular way. Points can be drawn as points, icons, or heatmaps. Lines may be drawn with color and widths, and polygons with color, borders, and labels. A layer specification is made up of a number of parameters that instruct the Visual API how to draw the information. An example is thus:

from=us_census00.zcta_geom|mode=simple|border=black_1|colors=clear

By the end of this tutorial, we promise you'll understand what it means.

Mapping Point Locations

Points for EPA Brownfields

The first thing we'll map is point locations of EPA brownfields where air contamination was found in 2009.

By using the Data Catalog as described in the Mapfluence Overview, you can find that the name of the dataset is

epabrnfld.bf2009_geom

and the name of the attribute 2009 air contamination is

epabrnfld.bf2009.air_f

You might imagine that if you wanted to create a SQL query to get information about brownfields, you might create a SQL statement like this:

SELECT geometry
FROM epabrnfld.bf2009_geom
WHERE epabrnfld.bf2009.air_f = 't'

and in fact, that is very similar to what a Mapfluence query looks like, except that it is not necessary to select the geometry. The part of a Mapfluence URL to make this map related to selecting the data looks like this:

from=epabrnfld.bf2009_geom|where=epabrnfld.bf2009.air_f:t

You want this data to appear on a map, however, which means that you need to specify a little bit about the points: what color, what size, etc. Let's say that you want the points to be black and 7 pixels in diameter. In that case, your color description will look like this:

mode=simple|colors=black_7

(This uses the simplest way of describing colors (mode=simple); you will learn about more complicated ways of describing colors later.)

Now you need to assemble everything into a URL. At the beginning of the URL, you need to put

http://lab.mapfluence.com/map/d/

and at the end, you need to give Mapfluence a code for which mapping service to use: Google Maps ("g"), Bing Maps (formerly Virtual Earth, or "ve"), or OpenLayers (which uses Tile Mapping Service tiles, so "tms"). We'll use Bing Maps for all of our examples.

Additionally, we want to set the initial latitiude, longitude and zoom level to show the continental United States. We do this by adding the query arguments "lat", "lng" and "zoom". The full URL looks like this:

http://lab.mapfluence.com/map/d/from=epabrnfld.bf2009_geom|where=epabrnfld.bf2009.air_f:t|mode=simple|colors=black_7/ve/?lng=-97.337545&lat=37.692236&zoom=3

Look at the brownfield locations map!

Icons for Airports

Airport locations are great to know; many people want to be close but not too close. Points can be styled as either dots or icons. Mapfluence has a number of icons available (registered users can also programmatically add new ones).

On the icons page you will note that there is an icon with the identifier "icon_air_transportation". For the Visual API, specify the icon and size like so: <identifier>_<width>x<height>

icons=icon_air_transportation_24x20

In the catalog, you'll find this airports dataset, with a a geometry table called:

ntad_airports.arpt_loc_geom

A map with just the airports looks like this:

http://visual.mapfluence.com/map/d/
from=ntad_airports.arpt_loc_geom|mode=simple|
icons=icon_air_transportation_24x20/ve/?zoom=8

Look at the airport locations map!

You will see later how to combine the various layers onto one map.

Mapping Polygons

Solid Polygons for Home Prices

The US Census contains a treasure trove of data. In the data catalog, searching for census, you'll find Census Demographics and Boundaries. The Census data tables include over a thousand variables; among them home prices. Find a variable that captures your interest. In this example we use:

Typical (median) value of an owner-occupied home in 2000. (us_census00.stats.med_hv)

You specify this in the select clause of the map definition:

select=us_census00.stats.med_hv

In the case of census data, you can show the data for various different geometry types: by state, by county, by census tract, by zip code, by municipality, by metropolitan area, or by census block group. For this application, it probably makes sense to use census tracts, which have the code name:

us_census00.tract_geom

You specify this in the from clause (which tells us what geometries to draw):

from=us_census00.tract_geom

There are two possible ways to show the data: you could show only areas where the median home value is under a certain amount, for example USD$400,000, or could instead show different colors depending upon what the median home value is.

To only color in areas where the median home value is under USD$400,000, you would need to specify a where clause that selects only for that condition:

where=us_census00.stats.med_hv__lt:400000

You then would need to specify the colors, which you would do with a fragment that looks something like the following:

mode=simple|colors=yellow

Putting it all together, the URL for that map would look like this:

http://visual.mapfluence.com/map/d/select=us_census00.stats.med_hv|from=us_census00.tract_geom|where=us_census00.stats.med_hv__lt:400000|mode=simple|colors=yellow/ve/

Look at the under $400K map!

If instead of not showing areas where the price was high, you wanted to show a different color for each price range, you would specify the price ranges in which you are interested as well as which color should correspond to each of those ranges. For example, suppose you wanted to show:

value color
below $200,000 white
$200,001 to $ 400,000 blue
$400,001 to $ 600,000 green
$600,001 to $ 800,000 yellow
$800,001 to $1,000,000 orange
over $1M red

In that case, you would need to use the color mode "theme".

mode=theme

You then need to specify the points at which the colors should change: 200000, 400000, 600000, 800000, and 1000000.

breaks=200000,400000,600000,800000,1000000

You also need to specify the colors: white, blue, green, yellow, orange, and red. You do so like this:

colors=white,blue,green,yellow,orange,red

Note the parallel structure between breaks and colors, and that there is always one more color than break.

Putting it all together, a URL for a map that colors the ranges in the above manner looks like this:

http://visual.mapfluence.com/map/d/select=us_census00.stats.med_hv|from=us_census00.tract_geom|breaks=200000,400000,600000,800000,1000000|mode=theme|colors= white,blue,green,yellow,orange,red/ve/

Look at the median home value map!

Transparency, Colors, and Alpha

The ownership map above is informative, but it blocks out all context. Instead of specifying solid colors, you may specify a color with an alpha channel value. This is done by specifying an RGBA value. You're probably familiar with RGB from web development ("#FF0000" is red); RGBA is the same with an extra byte tacked on at the end. Given a desired transparency value (t) between 0 to 1.0 (opaque to totally transparent), the hex alpha value is:

hex(int(255*(1-t)))

So: opaque red in RGBA is "FF0000FF"; 50% transparent is "FF000080", etc. Our same color scheme as above with 50% transparency is:

colors=FFFFFF80,0000FF80,00FF0080,FFA50080,FF000080

Here is the transparent overlay map.

For quick reference:

Opacity hex values
% transparent hex
75 3F
50 80
25 BF
0 FF

Outlines for Unified School Districts

For this map, you won't want to obscure the home value information, so you'll want to only draw the borders of the polygons.

The unified school district geometry set's code name is:

us_schl_dists.uni2008_geom

so your from clause will look like this:

from=us_schl_dists.uni2008_geom

To draw only the borders, you need to make the color of the polygons transparent. Fortunately, there is a named color "clear" which will draw transparent color (i.e. show what is underneath).

colors=clear

To specify the color and size of the border, use the border clause:

border=black_1

Putting it all together, the school district borders map looks like this

http://visual.mapfluence.com/map/d/
from=us_schl_dists.uni2008_geom|
mode=simple|border=black_1|colors=clear/ve/

Look at the school district boundary map!

Multiple Layers

You have all these individual maps, but you want to put them all together. The full URL syntax looks like:

http://visual.mapfluence.com/map/d/<layerspecs>/<maptype>/

and end with the same thing -- /g/, /ve/, or /tms/.

For the layerspecs, join order them together with a slash (/) ordered from bottom to top:

  • select=us_census00.stats.med_hv|from=us_census00.tract_geom|mode=theme|breaks=200000,400000,600000,800000,1000000|colors=FFFFFF80,0000FF80,00FF0080,FFA50080,FF000080
  • from=us_schl_dists.uni2008_geom|mode=simple|border=black_1|colors=clear
  • from=schoolperfed_com.sch_info_geom|mode=simple|colors=black_7
  • from=ntad_airports.arpt_loc_geom|mode=simple|icons=icon_air_transportation_24x20

The result looks like this:

http://visual.mapfluence.com/map/d/select=us_census00.stats.med_hv|from=us_census00.tract_geom|mode=theme|breaks=200000,400000,600000,800000,1000000|colors=FFFFFF80,0000FF80,00FF0080,FFA50080,FF000080/from=us_schl_dists.uni2008_geom|mode=simple|border=black_1|colors=clear/from=schoolperfed_com.sch_info_geom|mode=simple|colors=black_7/from=ntad_airports.arpt_loc_geom|mode=simple|icons=icon_air_transportation_24x20/ve/

Moving to Javascript

EasyMap is a shortcut.

To embed maps in a Javascript/HTML page, you need a little bit of scaffolding. You need to include some scripts, set up your HTML, include an UMI API key, and so on.

The best way to get started with Javascript is to just pick one of the map URLs above that looks similar to what you are interested in, and copy and modify it.

Take a look at the code. Regardless of which mapping framework you are using, their mapping API allows you to specify a tile template: a URL pattern with slots held open for the mapping framework to put specific tile coordinates into. For Bing Maps, the template for the housing price map is created with the following code:

function tilePath(tileContext)
{
    return "/tile/1.0.0/d/select%3Dus_census00.stats.med_hv%7Cfrom%3Dus_census00.tract_geom%7Cmode%3Dtheme%7Cbreaks%3D200000%2C400000%2C600000%2C800000%2C1000000%7Ccolors%3DFFFFFF80%2C0000FF80%2C00FF0080%2CFFA50080%2CFF000080/g/" + tileContext.ZoomLevel + '/' + tileContext.XPos + '/' + tileContext.YPos + '.png?apikey=YOUR_API_KEY';
}

function GetTiles()
{
    var bounds = [new VELatLongRectangle(new VELatLong(90,-180),new VELatLong(-90,180))];

    var tileSourceSpec = new VETileSourceSpecification("overlay", "");
    tileSourceSpec.NumServers = 1;
    tileSourceSpec.Bounds = bounds;
    tileSourceSpec.MinZoomLevel = 0;
    tileSourceSpec.MaxZoomLevel = 16;
    tileSourceSpec.Opacity = 1;
    tileSourceSpec.ZIndex = 100;
    tileSourceSpec.GetTilePath = tilePath;

    map.AddTileLayer(tileSourceSpec, true);
}

You should recognize the stuff in the middle of tilePath as the url-encoded layer specification. The tileContext.ZoomLevel, .XPos, and .YPos are all instructions for which tile to fetch, which the Bing Maps API framework passes in (indirectly). Google Maps and TMS do much the same thing.

While you can now skin this page to your heart's content, it's still a little bit difficult to change things programmatically, like if you want to add checkboxes to show/hide the different layers. It is possible with this style of map, but your life will be better if you read on to the next section.

Advanced Javascript

Mapfluence offers a Javascript API for creating layer (tile) specifications, that will work will in a dynamic user interface: turn layers on and off, change breaks, etc. You can also make maps with Javascript objects.

Bing (VE), Google, Cloudmade, and TMS (OpenLayers), each have convenience classes - TileManagers - to make life a little easier:

function GetMap()
{
   map = new VEMap('myMap');  // connects the map div to the API
   map.SetDashboardSize(VEDashboardSize.Small);
   map.LoadMap(new VELatLong(37.76,-122.4),11,'r' ,false);

   mgr = new MF.VE.TileManager({
       opacity: 0.5,
       tileSpec: new MF.Render.TileSpec({
           layers: [
                   new MF.Render.SimpleLayer({
                           from: 'ntad_airports.arpt_loc_geom',
                           icons: 'icon_air_transportation_24x20'})
                   ] // use the same parameter names and values
        })
   });

   mgr.overlay(map);  // This is it!
}

You will probably recognize some of the airport map's parameters in the layers field of the tileSpec:

new MF.Render.SimpleLayer({
        from: 'ntad_airports.arpt_loc_geom',
        icons: 'icon_air_transportation_24x20'})

Here is the layer for the schools:

new MF.Render.SimpleLayer({
        from: 'schoolperfed_com.sch_info_geom',
        colors: 'black_7'})

Here is the layer for the median housing price:

new MF.Render.ThemeLayer({
        select: 'us_census00.stats.med_hv',
        from: 'us_census00.tract_geom',
        breaks: [200000,400000,600000,800000,1000000],
        colors: ['FFFFFF80','0000FF80','00FF0080','FFA50080','FF000080']})

Notice that the mode clause shows up in the type of the layer: MF.Render.SimpleLayer for the airports and schools; MF.Render.ThemeLayer for the median housing value layer.

Finally, here is the layer for the school districts:

new MF.Render.SimpleLayer({
        from: 'us_schl_dists.uni2008_geom',
        border: new MF.Render.Border('black','1.0'),
        colors: 'clear'})

To put them all together, just put them all in the layers array. The first layer in the layers array gets drawn first, so we need to order our layers so that the median home value doesn't obscure the other layers:

tileSpec: new MF.Render.TileSpec({
    layers: [
            new MF.Render.ThemeLayer({
                    select: 'us_census00.stats.med_hv',
                    from: 'us_census00.tract_geom',
                    breaks: [200000,400000,600000,800000,1000000],
                    colors: ['FFFFFF80','0000FF80','00FF0080','FFA50080','FF000080']}),
            new MF.Render.SimpleLayer({
                    from: 'us_schl_dists.uni2008_geom',
                    border: new MF.Render.Border('black','1.0'),
                    colors: 'clear'}),
            new MF.Render.SimpleLayer({
                    from: 'ntad_airports.arpt_loc_geom',
                    icons: 'icon_air_transportation_24x20'}),
            new MF.Render.SimpleLayer({
                    from: 'schoolperfed_com.sch_info_geom',
                    colors: 'black_7'})
            ]

To run this, you can go to the Mapfluence API Developer Lab and enter the following full Easy Map example:

// apilab-template: code-evaluates-to-url

var easy_map = new MF.EasyMap({
        tileSpec: new MF.Render.TileSpec({
           layers: [
                   new MF.Render.ThemeLayer({
                           select: 'us_census00.stats.med_hv',
                           from: 'us_census00.tract_geom',
                           breaks: [200000,400000,600000,800000,1000000],
                           colors: ['FFFFFF80','0000FF80','00FF0080','FFA50080','FF000080']}),
                   new MF.Render.SimpleLayer({
                           from: 'us_schl_dists.uni2008_geom',
                           border: new MF.Render.Border('black','1.0'),
                           colors: 'clear'}),
                   new MF.Render.SimpleLayer({
                           from: 'ntad_airports.arpt_loc_geom',
                           icons: 'icon_air_transportation_24x20'}),
                   new MF.Render.SimpleLayer({
                           from: 'schoolperfed_com.sch_info_geom',
                           colors: 'black_7'})
                   ]

           }),
           // map type can be one of 'bing','google','openlayers','cloudmade'
           maptype: 'bing'
})
easy_map.getMapUrl();

Next... The Query API

You've provided the map. But now users have specific questions, "That looks interesting! Tell me more!" That brings us to the Query API: the suite of tools that allow you to answer precise questions about place, and leverage the enormous corpus of data in Mapfluence...

So on to the Query API!