Search code examples
leafletbufferturfjs

Turf.js pointsWithinPolygon - creating a usable array


I've read through the docu on Turf.js pointsWithinPolygon and understand that it requires an array. I know what I want to accomplish but I'm not sure how to properly transform my L.geoJSON layers to satisfy the array condition. Please excuse the strange formatting as I've been playing around a lot lately and have lost some structure.

My points are:

    var employees2 = L.geoJSON();    
        
    Papa.parse('src/data1/Employees.csv', {
                        header: true,
                        download: true,
                        dynamicTyping: true,
                        skipEmptyLines: true,
                        complete: function(results) {
                            results.data.forEach((employee) => {
                                feature = {
                                    "type": "Feature",
                                    "geometry": {
                                      "type": "Point",
                                      "coordinates": [employee.Long, employee.Lat]
                                    },
                                    "properties": {
                                      "Postal Code": employee.Pcode
                                    }
                                  }
                                
                                       mrkEmployees = L.geoJSON(feature, {
                                           pointToLayer: function (feature, latlng){
                                               return L.marker(latlng, {icon: redcircle});
                                           }
                                           
                                       }).addTo(employees2)
                                mrkEmployees.bindPopup(employee.Pcode)
                            })
                        }
    });

and my polygons (which are turf buffers) are:

        var buffers2 = L.geoJSON();
       
        // parse local CSV file
        
        Papa.parse('src/data1/Houses.csv', {
                        header: true,
                        download: true,
                        dynamicTyping: true,
                        skipEmptyLines: true,
                        complete: function(results) {
                            results.data.forEach((house) => {
                                feature = {
                                    "type": "Feature",
                                    "geometry": {
                                      "type": "Point",
                                      "coordinates": [house.Longitude, house.Latitude]
                                    },
                                    "properties": {
                                      "Location": house.Location,
                                      "Type": house.Type
                                    }
                                  }
                                
                                       mrkHouses = L.geoJSON(feature).addTo(houses)
                                        houseBuffer = turf.buffer(mrkHouses.toGeoJSON(), 5, {units: 'kilometers'});
                                        lyrTest = L.geoJSON(houseBuffer, {style: 
                                                house.Type === 'Duplex' ? { color: "blue" } : 
                                                house.Type === 'Quadplex' ? { color: "yellow" } :
                                                { color: "red"}}).addTo(buffers2)
                                
                                        mrkHouses.bindPopup(house.Location);
                                        lyrTest.bindPopup("5km Buffer");
                                

                            })
                    }
            }); 

The part that is confusing me is how to pull out my array as many of my properties are defined within my parsed CSV code block and is therefore producing errors when trying to call coordinates.

Learning as I go. Afterward successfully defining the pointsWithinPolygon, I am going to attempt to export (save externally) said points as a layer - in case context helps.

Thanks as always - this community is very generous and extremely helpful.

EDIT - See DEMO file.

enter image description here


Solution

  • Don't add the feature to a GeoJSON-Group, to add the group again to a GeoJSON-Group. One time is enough.

    var employeesData = L.geoJSON(null,{
        pointToLayer: function (feature, latlng) {
            return L.marker(latlng, {icon: redcircle});
        },
        onEachFeature: function (feature, layer) {
            layer.bindPopup(feature.properties["Postal Code"])
        }
    }).addTo(map);
    ...
    ...Papa loop
    results.data.forEach((employee) => {
                var feature = {
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [employee.Long, employee.Lat]
                    },
                    "properties": {
                        "Postal Code": employee.Pcode
                    }
                };
                employeesData.addData(feature);
            })
    

    Same for the buffer (I splitted the data and the buffers into seperate groups):

    var housesData = L.geoJSON(null,{
        onEachFeature: function (feature, layer) {
            layer.bindPopup(feature.properties.Location)
        }
    }).addTo(map);
    
    var buffersData = L.geoJSON(null,{
        style: function (feature) {
            return feature.properties.Type === 'Duplex' ? { color: "blue" } : feature.properties.Type === 'Quadplex' ? { color: "yellow" } : { color: "red"}
        },
        onEachFeature: function (feature, layer) {
            layer.bindPopup("5km Buffer")
        }
    }).addTo(map);
    
    ... Papa loop
                housesData.addData(feature);
                buffersData.addData(turf.buffer(feature, 5, {units: 'kilometers'}));
    
    

    And then you can check if the points in the buffers: (I don't know if the the first function is working, if not you have to check for each buffer if the points is in it getPointsInPolygonForEachBuffer)

    var pointsInBuffer;
    function getPointsInPolygon(){
        var ptsWithin = turf.pointsWithinPolygon(employeesData.toGeoJSON(), buffersData.toGeoJSON());
        pointsInBuffer = L.geoJSON(ptsWithin).addTo(map);
    }
    
    function getPointsInPolygonForEachBuffer(){
        pointsInBuffer = L.geoJSON().addTo(map);
        buffersData.eachLayer((layer)=>{
            var ptsWithin = turf.pointsWithinPolygon(employeesData.toGeoJSON(), layer.toGeoJSON());
            pointsInBuffer.addData(ptsWithin);
        })
    }
    

    Complete code:

    var employeesData = L.geoJSON(null,{
    pointToLayer: function (feature, latlng) {
        return L.marker(latlng, {icon: redcircle});
    },
    onEachFeature: function (feature, layer) {
        layer.bindPopup(feature.properties["Postal Code"])
    }
    }).addTo(map);
    
    var housesData = L.geoJSON(null,{
    onEachFeature: function (feature, layer) {
        layer.bindPopup(feature.properties.Location)
    }
    }).addTo(map);
    
    var buffersData = L.geoJSON(null,{
    style: function (feature) {
        return feature.properties.Type === 'Duplex' ? { color: "blue" } : feature.properties.Type === 'Quadplex' ? { color: "yellow" } : { color: "red"}
    },
    onEachFeature: function (feature, layer) {
        layer.bindPopup("5km Buffer")
    }
    }).addTo(map);
    
    
    Papa.parse('src/data1/Employees.csv', {
    header: true,
    download: true,
    dynamicTyping: true,
    skipEmptyLines: true,
    complete: function(results) {
        results.data.forEach((employee) => {
            var feature = {
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [employee.Long, employee.Lat]
                },
                "properties": {
                    "Postal Code": employee.Pcode
                }
            };
            employeesData.addData(feature);
        })
    }
    });
    
    
    // parse local CSV file
    Papa.parse('src/data1/Houses.csv', {
    header: true,
    download: true,
    dynamicTyping: true,
    skipEmptyLines: true,
    complete: function(results) {
        results.data.forEach((house) => {
            var feature = {
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    "coordinates": [house.Longitude, house.Latitude]
                },
                "properties": {
                    "Location": house.Location,
                    "Type": house.Type
                }
            };
            housesData.addData(feature);
            buffersData.addData(turf.buffer(feature, 5, {units: 'kilometers'}));
        })
    }
    });
    
    
    var pointsInBuffer;
    function getPointsInPolygon(){
    var ptsWithin = turf.pointsWithinPolygon(employeesData.toGeoJSON(), buffersData.toGeoJSON());
    pointsInBuffer = L.geoJSON(ptsWithin).addTo(map);
    }
    
    function getPointsInPolygonForEachBuffer(){
    pointsInBuffer = L.geoJSON().addTo(map);
    buffersData.eachLayer((layer)=>{
        var ptsWithin = turf.pointsWithinPolygon(employeesData.toGeoJSON(), layer.toGeoJSON());
        pointsInBuffer.addData(ptsWithin);
    })
    }