Leaflet WFS – Dynamically Adding Lat, Lon Filters to Enhance Data Requests

ajaxgeojsonhtmlleafletwfs

I want to run my wfs_url for all the points/cities returned by:-https://demo.pygeoapi.io/master/collections/ogr_gpkg_poi/items?f=json request? such that my result will show the no of earthquake data within a distance of 1450 km from city. However, I have tried this process, adding coordinate value of each city to run my wfs_url and this has made my script look ugly.
i.e. https://emidius.mi.ingv.it/services/italy/wfs/?service=wfs&version=2.0.0&request=GetFeature&typeNames=italy:CPTI_current&outputFormat=application/json&CQL_FILTER=dwithin(geom, MULTIPOINT((41.701259 -7.5005), (40.655991 -7.917709), (40.200475 -8.419193),(40.198381 -7.639009),(40.087058 -8.290237),(39.369447 -9.391943),(38.443198 -9.100006),(38.448289 -9.130834),(32.748972 -16.697671)), 1450, kilometers).

Has someone an idea how it can be done. The code is shown below:-

    <html>
<head>
  <title>Creating mash-ups with Leaflet</title>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
  <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="https://auth.airmap.com/js/keycloak.js"></script>
  <style>
    html,
    body {
      height: 100%;
      margin: 0;
    }
    #map {
      width: 800px;
      height: 600px;
    }
  </style>
  <head>
    <body>
      <div id="map"></div>
      <script>
        var map = L.map('map').setView([14.6361111, 42.1608333], 8);
        var wmsLayer = L.tileLayer.wms('https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv?', {
          layers: 'GEBCO_LATEST_SUB_ICE_TOPO'
        }).addTo(map);

        var elevation;
        $.getJSON('https://demo.pygeoapi.io/master/collections/ogr_gpkg_poi/items?f=json', function(value) {
          var datalayer = L.geoJson(value, {
            onEachFeature: function(feature, featureLayer) {
              var lon = feature.geometry.coordinates[0];
              var lat = feature.geometry.coordinates[1];
              var city = feature.properties.name;

              $.ajax({
                url: 'https://api.airmap.com/elevation/v1/ele/?points=' + lat + ',' + lon +
                  '&units=metric& appid=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjcmVkZW50aWFsX2lkIjoiY3JlZGVudGlhbHxwQUFNWlBxaEx2T2Q2cGZSR2JkMlhDQkdRcTdNIiwiYXBwbGljYXRpb25faWQiOiJhcHBsaWNhdGlvbnx3ZURHZ01oTldtek55c1A4S0xEdlRsQW5QTE0iLCJvcmdhbml6YXRpb25faWQiOiJkZXZlbG9wZXJ8MnpvYmI3eWh4ZVk0cWtDM1BSeDBaSEtNejIzOCIsImlhdCI6MTQ3MTM3OTc0Mn0.MeO0jt6holPt0jdPJvRJrTBi380WsbOPGCEO6u-tfSo',
                async: false,
                dataType: 'json',
                success: function(json) {
                  elevation = json.data;
                }
              });
              featureLayer.bindPopup("City: " + city + "</br>Elevation: " + elevation + "metres");
            }
          }).addTo(map);
        });

var wfs_url = "https://emidius.mi.ingv.it/services/italy/wfs/?service=wfs&version=2.0.0&request=GetFeature&typeNames=italy:CPTI_current&outputFormat=application/json&CQL_FILTER=dwithin(geom, MULTIPOINT((41.701259 -7.5005), (40.655991 -7.917709), (40.200475 -8.419193),(40.198381 -7.639009),(40.087058 -8.290237),(39.369447 -9.391943),(38.443198 -9.100006),(38.448289 -9.130834),(32.748972 -16.697671)), 1450, kilometers)";
 $.getJSON(wfs_url).then((res) => {
  var layer = L.geoJson(res, {
    onEachFeature: function (feature, layer) {
      var popupTxt = 'Epicentral area: ' + feature.properties.EpicentralArea + '<br>' +
                     'Year: ' + feature.properties.Year +  '<br>' +
                     'Magnitude: ' + feature.properties.MwDef
      layer.bindPopup(popupTxt);
    }      
  }).addTo(map);
  map.fitBounds(layer.getBounds());
});
      </script>
    </body>
</html>

Best Answer

All you have to do is to save city coordinates, as they are being retrieved with the first GeoJSON request, to an array, then loop through this array and construct point filter, which can then be used in in the second GeoJSON request.

Relevant part of the code could then look something like this:

$.getJSON('https://demo.pygeoapi.io/master/collections/ogr_gpkg_poi/items?f=json', function(value) {
  var coords = [];   // Array to save city coordinates
  var datalayer = L.geoJson(value, {
    onEachFeature: function(feature, featureLayer) {
      var lon = feature.geometry.coordinates[0];
      var lat = feature.geometry.coordinates[1];
      var city = feature.properties.name;
      coords.push([lon, lat]);
      $.ajax({
        url: 'https://api.airmap.com/elevation/v1/ele/?points=' + lat + ',' + lon +
          '&units=metric& appid=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjcmVkZW50aWFsX2lkIjoiY3JlZGVudGlhbHxwQUFNWlBxaEx2T2Q2cGZSR2JkMlhDQkdRcTdNIiwiYXBwbGljYXRpb25faWQiOiJhcHBsaWNhdGlvbnx3ZURHZ01oTldtek55c1A4S0xEdlRsQW5QTE0iLCJvcmdhbml6YXRpb25faWQiOiJkZXZlbG9wZXJ8MnpvYmI3eWh4ZVk0cWtDM1BSeDBaSEtNejIzOCIsImlhdCI6MTQ3MTM3OTc0Mn0.MeO0jt6holPt0jdPJvRJrTBi380WsbOPGCEO6u-tfSo',
        async: false,
        dataType: 'json',
        success: function(json) {
          elevation = json.data;
        }
      });
      featureLayer.bindPopup("City: " + city + "</br>Elevation: " + elevation + "metres");
    }
  }).addTo(map);
  var coordsStr = '';  // Points filter
  for (var i = 0; i < coords.length; i++) {
    if (i > 0) coordsStr += ',';
    coordsStr += '(' + coords[i][1] + ' ' + coords[i][0] + ')';
  }
  var wfs_url = "https://emidius.mi.ingv.it/services/italy/wfs/?service=wfs&version=2.0.0&request=GetFeature&typeNames=italy:CPTI_current&outputFormat=application/json&"
              + "CQL_FILTER=dwithin(geom, MULTIPOINT(" + coordsStr + "), 1450, kilometers)";
   $.getJSON(wfs_url).then((res) => {
    var layer = L.geoJson(res, {
      onEachFeature: function (feature, layer) {
        var popupTxt = 'Epicentral area: ' + feature.properties.EpicentralArea + '<br>' +
                       'Year: ' + feature.properties.Year +  '<br>' +
                       'Magnitude: ' + feature.properties.MwDef
        layer.bindPopup(popupTxt);
      }      
    }).addTo(map);
    map.fitBounds(layer.getBounds());
  });
});