Search code examples
javascriptangularjsleafletmapboxgeojson

Get geoJSON data from mapbox API to determine point in polygon


I recently followed this tutorial to determine if a point shown by a marker sits inside a defined polygon: https://www.mapbox.com/mapbox.js/example/v1.0.0/point-in-polygon/

Works great, but they pull in the polygon geoJSON data with ajax and apply it to the map. I have a mapbox map already built with a polygon area drawn. I'm using their API to display my map. I now need to access the geoJSON data to determine if a point is within an area. How can I access that data through the API?

Here's how I pull in the map, the geoJSON and a function to test if a point is in a geoJSON area:

//mapbox connection
var mapID = "<map-id>";
L.mapbox.accessToken = "<my-token>";

//init map
var map = L.mapbox.map("mapData", mapID, {
  attributionControl: false, 
  zoomControl: false
}).setView([53.799, -1.548], 13, {
  pan: { animate: true },
  zoom: { animate: true } 
});

//get geoJSON
var geoJson;
$http.get("https://a.tiles.mapbox.com/v4/" + mapID + "/features.json?access_token=" + L.mapbox.accessToken).success(function(data){
  geoJson = data;
});

//determine point in polygon
function determinePointInPolygon(){
  var coords = [-1.3, 5.2];
  var layer = leafletPip.pointInLayer(coords, L.geoJson(geoJson), true);
  if (!layer.length) //point not in polygon
  else //point is in polygon
}

Solution

  • The integrated features are loaded into a L.mapbox.featureLayer which is available as a member of your L.mapbox.Map instance. Let's say you have your map instance stored in a reference called map your layer would be map.featureLayer:

    // Make sure the featureLayer is ready
    map.featureLayer.on('ready', function (e) {
        // Loop over the features
        e.target.eachLayer(function (layer) {
            // Do your thing
            // here "layer" holds an instance of the marker/polygon/polyline
            // "layer.feature" holds the actual geojson feature
        });
    });
    

    Here's an example of the concept: http://plnkr.co/edit/D5IfRTLV0yXTqOmzNCYA?p=preview

    You could also load the tiles and features seperately if you wish, instanciate your map with no mapid:

    var map = L.mapbox.map('mapbox', null, {
        'center': [0, 0],
        'zoom': 1
    });
    
    var tileLayer = L.mapbox.tileLayer('yourMapId').addTo(map);
    
    var featureLayer = L.mapbox.featureLayer('yourMapId').addTo(map);
    

    Example: http://plnkr.co/edit/9pYeRu6UmxuVL1TLzwPR?p=preview

    Then you could leave out the addTo method, first process your features and then add the layer to the map:

    var featureLayer = L.mapbox.featureLayer('yourMapId');
    // Make sure the featureLayer is ready
    featureLayer.on('ready', function (e) {
        // Loop over the features
        e.target.eachLayer(function (layer) {
            // Do your thing
        });
        // Add layer to the map
        e.target.addTo(map);
    });
    

    What ever works best for you. But i almost forgot to actually answer your question (although i think you won't be needing this anymore), the actual GeoJSON featurecollection can be obtained by using L.mapbox.FeatureLayer's getGeoJSON method (only when the layer is ready ofcourse):

    // Make sure the featureLayer is ready
    featureLayer.on('ready', function (e) {
        // Fetch you featurecollection
        var geojson = e.target.getGeoJSON();
    });