0

Leaflet and Turf. I am trying find all the layers on a Leaflet map that intersect a point when the user clicks on the map. I am using the turf library to test for this. In the console when I click on the map it returns this error:

turf.min.js:1 Uncaught Error: geojson must be a valid Feature or Geometry Object
    at J (turf.min.js:1)
    at Object.Lo [as intersect] (turf.min.js:1)
    at js2.js:22
    at eachLayer (leaflet.js:5)
    at e.<anonymous> (js2.js:20)
    at e.fire (leaflet.js:5)
    at e._fireDOMEvent (leaflet.js:5)
    at e._handleDOMEvent (leaflet.js:5)
    at HTMLDivElement.r (leaflet.js:5)

Here is the code

map.on('click', function(e) {
        var str = "Latitude: " + e.latlng.lat.toFixed(5) + " Longitude: " + e.latlng.lng.toFixed(5) + " Zoom Level: " + map.getZoom();
        var lat = e.latlng.lat;
        var lng = e.latlng.lng;
        var pt = turf.point([lng, lat]);

        map.eachLayer(function(layer) {
            if (layer instanceof L.GeoJSON) {
                var click_intersection = turf.intersect(pt, layer.toGeoJSON());
                if (click_intersection) {
                    console.log(layer.feature.properties)
                }
            }
        });

Reference questions turf.js intersect problem?

Get popup info in multiple layers from one click

update

    var c = new L.GeoJSON.AJAX("http://127.0.0.1:8000/childcare_buff_data/",{
        style: color(c, "orange", 0.8)})
        ;
    c.addTo(map);

    map.on('click',function(e){
        lat = e.latlng.lat;
        lon = e.latlng.lng;
        ProcessClick(lat,lon)
    });

    var theMarker;
    var a;

    function ProcessClick(lat,lon){
        theMarker = L.marker([lat,lon]).addTo(map);
        c.eachLayer(function(layer) {
            intersects=turf.intersect(theMarker.toGeoJSON(),layer.toGeoJSON());
            if (intersects){
                a=layer.feature.properties.buff
                console.log(a);
                }
            })};

I get this error

turf.min.js:1 Uncaught TypeError: Cannot read property 'length' of null
    at turf.min.js:1
    at turf.min.js:1
    at S (turf.min.js:1)
    at Pn (turf.min.js:1)
    at Object.Lo [as intersect] (turf.min.js:1)
    at js2.js:31
    at eachLayer (leaflet.js:5)
    at ProcessClick (js2.js:30)
    at e.<anonymous> (js2.js:22)
    at e.fire (leaflet.js:5)

enter image description here

here is the geojson http://www.mediafire.com/file/9fnbz32ib9n1aaj/childcare.geojson/file

0

Okay, here is a possible solution, I used, 3 layers, muni, county, state, variables, a,b,c, when I would click on the map and it would grab the polygons feature Name from each layer, Then I posted the three feature Names to a dialog. Here is the process to get the values.I also create a marker to see where I clicked.

  map.on('click',function(e){  
        lat = e.latlng.lat;
        lon = e.latlng.lng;
        ProcessClick(lat,lon)   
  });

var theMarker;
var a;
var b;
var c;

function ProcessClick(lat,lon){

    if (theMarker != undefined) {
              map.removeLayer(theMarker);
        };
        if (newgeojsonLayer != undefined) {
              map.removeLayer(newgeojsonLayer);
        };  


    theMarker = L.marker([lat,lon]).addTo(map);  //added to show where you clicked.

        muniLayer.eachLayer(function (layer) {

        //isInside =turf.inside(theMarker.toGeoJSON(), layer.toGeoJSON());

       // Newer method in Turf
       isInside =turf.booleanPointInPolygon((theMarker.toGeoJSON(), layer.toGeoJSON());

        if (isInside){
                a = "City/Town: " + layer.feature.properties.NAME;
                console.log("City/Town: " + layer.feature.properties.NAME);
        }
    });

    countyLayer.eachLayer(function (layer) {

        isInside =turf.inside(theMarker.toGeoJSON(), layer.toGeoJSON());

        if (isInside){
                b = "County: " + layer.feature.properties.NAME;
                console.log("County: " + layer.feature.properties.NAME);
        }
    });

    stateLayer.eachLayer(function (layer) {

        isInside =turf.inside(theMarker.toGeoJSON(), layer.toGeoJSON());

        if (isInside){
            console.log("State: " + layer.feature.properties.STATE_NAME);
            c = "State: " + layer.feature.properties.STATE_NAME;
        }
    })

}

Basically I used it as a popup for all three layers, I just put the values for a,b,c in the popup dialog.

http://www.gistechsolutions.com/leaflet/DEMO/pointsinpoly/index.html http://www.gistechsolutions.com/leaflet/DEMO/pointsinpoly/indextab.html

  • thanks for the code Bill -- i updated my code to reflect part of what you posted but got an error. also turf.inside was not a function I had in the turf library but I figured intersect would work fine – ziggy Mar 15 at 15:59
  • If you want, grab or refer to the version I used. – Bill Chappell Mar 15 at 16:03
  • but shouldn't intersect work? im trying PointsWithinPolygon but thats not working either – ziggy Mar 15 at 16:14
  • change your answer to turf.booleanPointInPolygon instead of turf.inside and I will accept your answer – ziggy Mar 21 at 14:35
  • 1
    2 ways to do that. Option 1. Here is a writeup showing how I did it with the layer._leaflet_id option. See ForEachFeature function. gistechsolutions.com/leaflet/DEMO/Search/index.html From your inside function use the Name to select the polygon, and have a highlight style. Option 2. Create array (var selfeat = [];), and if the feature is inside then add it to the array. selfeat.push(layer.feature); Then make a new layer out of the array. geojsonLayer = L.geoJson(selfeat, { gistechsolutions.com/leaflet/DEMO/Select/PolySelect.html – Bill Chappell Mar 21 at 15:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.