Retrieve Neighbourhoods

Retrieve Neighbourhoods

The Who’s On First API allows you to query and retrieve Who’s On First data including neighbourhood data via a REST-ish interface.

In this tutorial, you will use the API to retrieve San Francisco's neighbourhoods and display them on a map. To do this, you will:

  1. Create a Map
  2. Find Info With Spelunker
  3. Retrieve Data using the API
  4. Display the data

Step 1: Create a Map

We are going to utilize mapzen.js to make our initial map.

To do this, we need to create an html page. Use the code below to create the map.

  <!DOCTYPE html>
<html lang="en">
  <head>
  <title>My Web Map</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="https://mapzen.com/js/mapzen.css">
  <script src="https://mapzen.com/js/mapzen.min.js"></script>
  style>
    #map {
      height: 100%;
      width: 100%;
      position: absolute;
    }
    html,body{margin: 0; padding: 0;}
  </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      L.Mapzen.apiKey = 'your-mapzen-api-key';
      var map = L.Mapzen.map('map', {
        tangramOptions: {
          scene: {
          import: [
            'https://mapzen.com/carto/refill-style/8/refill-style.zip', 'https://mapzen.com/carto/refill-style/8/themes/color-gray.zip', 'https://mapzen.com/carto/refill-style/8/themes/detail-1.zip'
          ]} 
        }
      });
      map.setView([37.77493, -122.41942], 12);
    </script>
  </body>
</html>

To learn more about mapzen.js, check out it's Get Started tutorial.

Step 2: Find Info With Spelunker

Now, we need some background info (WOF ID, latitude, longitude, etc...) to best utilize the API. To do this, we are going to take a look at the Spelunker.

Search for San Francisco in the Spelunker. Find the one that is the locality in the United States. You should find the page below.

Note the wof id. You can find it if you scroll down, it also the number located near the top of the page preceded by / and followed by .geojson. For San Francisco, this is 85922583.

Also, verify that you map is centered on the the right coordinates and the level is set correctly. For our purposes, we are going to level 14.

  <script>
  L.Mapzen.apiKey = 'your-mapzen-api-key';
  var map = L.Mapzen.map('map');
  map.setView([37.77493, -122.41942], 14);
</script>

Step 3: Retrieve Data using the API

To retrieve data using the API, we are going to utilize the mapzen.whosonfirst.api.js file.

Add the script to your html file.

<script src="mapzen.whosonfirst.api.js"></script>

Also add jquery we are going to use that later.

<script src="jquery.min.js"></script>

This script will allow you to make the queries available by the WOF API.

Add the following helper function to make those calls from your html file. Note that we are using the whosonfirst.places.getDescendants API method. We include mz:uri as an extra so we are able to retrieve a neighbourhood's geometry. Also note that we only want neighbourhood descendants.

  function runWhosOnFirstAPI() {
// Setup the API key
mapzen.whosonfirst.api.set_handler('authentication', function() {
  return 'your-mapzen-key';
});

// See: https://mapzen.com/documentation/wof/methods/#whosonfirst.places.getDescendants
// San Francisco's WOF ID
var parent_id = '85922583';
var method = 'whosonfirst.places.getDescendants';
var data = {
  id: '85922583',
  per_page: 500,
  extras: 'mz:uri,geom:latitude,geom:longitude', // this gets us lat/lng coords
  placetype: 'neighbourhood'
};

// Ok now we actually call the API
mapzen.whosonfirst.api.execute_method_paginated(method, data, onsuccess, onerror, onprogress);
};

Add the following helper functions. Not that the show_plane function has not yet been created.

  // NOOP (we are using onprogress instead)
var onsuccess = function() { return; };

// Just log errors to the JS console
var onerror = function(rsp) {
  console.error(rsp);
};

// Take all the API results and show them on the map
var onprogress = function(rsp) {
  //console.log(rsp);
  for (var i = 0; i < rsp.places.length; i++) {
    var place = rsp.places[i];
    show_plane(place);
  }
};

Step 4: Display the Data

Now we are going to display the data. To do this, we are going to write a show_plane function. The show_plane function takes a place's geometry and stylizes it with a fill and stroke. For our purposes, we are selecting random shades of gray.

  var show_plane = function(place) {
  $.get(place['mz:uri'], function(result) {
    L.geoJSON(result, {style: function (feature) {
      randomNumber1 = 86+Math.ceil(Math.random()*100);
      color = "rgb("+randomNumber1+","+randomNumber1+","+randomNumber1+")"
      return {color: '#888888', weight: 1, opacity: '.7', fillColor: color, fillOpacity: .5};
    }}).addTo(map);
  });
}

Your code should now resemble:

  <!DOCTYPE html>
<html lang="en">
  <head>
    <title>My Web Map</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://mapzen.com/js/mapzen.css">
    <script src="https://mapzen.com/js/mapzen.min.js"></script>
    <style>
      #map {
        height: 100%;
        width: 100%;
        position: absolute;
      }
      html,body{margin: 0; padding: 0;}
    </style>
  </head>
  <body onload="runWhosOnFirstAPI()">
    <div id="map"></div>
      <script src="../javascript/mapzen.whosonfirst.api.js"></script>
      <script src="../javascript/jquery.min.js"></script>
    <script>
    L.Mapzen.apiKey = 'mapzen-aetZmeQ';
    var map = L.Mapzen.map('map', {
      tangramOptions: {
        scene: {
          import: [
            'https://mapzen.com/carto/refill-style/8/refill-style.zip', 'https://mapzen.com/carto/refill-style/8/themes/color-gray.zip', 'https://mapzen.com/carto/refill-style/8/themes/detail-1.zip'
        ]} 
      }
    });
    map.setView([37.77493, -122.41942], 14);
			
    // How we should handle each API result
    var show_plane = function(place) {
      $.get(place['mz:uri'], function(result) {
        L.geoJSON(result, {style: function (feature) {
          randomNumber1 = 86+Math.ceil(Math.random()*100);
          color = "rgb("+randomNumber1+","+randomNumber1+","+randomNumber1+")"
          return {color: '#888888', weight: 1, opacity: '.7', fillColor: color, fillOpacity: .5};
        }}).addTo(map);
      });
    }

    // NOOP (we are using onprogress instead)
    var onsuccess = function() { return; };

    // Just log errors to the JS console
    var onerror = function(rsp) {
      console.error(rsp);
    };

    // Take all the API results and show them on the map
    var onprogress = function(rsp) {
      //console.log(rsp);
      for (var i = 0; i < rsp.places.length; i++) {
        var place = rsp.places[i];
        show_plane(place);
      }
    };

    function runWhosOnFirstAPI() {
      // Setup the API key
      mapzen.whosonfirst.api.set_handler('authentication', function() {
        return 'your-mapzen-key';
      });

      // Get all the venues in the Flatiron District
      // See: https://mapzen.com/documentation/wof/methods/#whosonfirst.places.getDescendants
      var parent_id = '85922583';
      var method = 'whosonfirst.places.getDescendants';
      var data = {
      id: parent_id,
      per_page: 500,
      extras: 'mz:uri,geom:latitude,geom:longitude', // this gets us lat/lng coords
      placetype: 'neighbourhood'
    };

    // Ok now we actually call the API
    mapzen.whosonfirst.api.execute_method_paginated(method, data, onsuccess, onerror, onprogress);
  };
  </script>
  </body>
</html>

When you refresh your html page, you should see this.

Congrats, you just made a map of San Francisco's neighbourhoods using the WOF API.