0

I am working on a school project where I have to create a Web Page where I should be able to use leaflet to create a route. I also have a JSON file with some Bike Docks. I need to find the nearest dock from the starting point of my trip and the nearest from the ending point of the route.

This is my code so far:

    <script>
        var map_var = L.map('map_id').setView([40.72730240765651, -73.9939667324035], 16);

        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        }).addTo(map_var);

        var startPosition = L.latLng();
        var endPosition = L.latLng();

        L.Routing.control({
            waypoints: [
                startPosition,
                endPosition,
            ],
            routeWhileDragging: true,
            collapsible: true,
            geocoder: L.Control.Geocoder.nominatim()
        }).addTo(map_var);

        $.getJSON("citybike.json", function (json1) {
            for (var i = 0; i < json1.stationBeanList.length; i++) {
                var place = json1.stationBeanList[i];
                coordinate = [place.latitude, place.longitude];

                /*var marker = L.marker(coordinate);
                marker.addTo(map_var).bindPopup(`<b>${place.stAddress1}</b><br>Status: ${place.statusValue}<br>Bici disponibili: ${place.availableBikes}<br>Docks disponibili: ${place.availableDocks}`);*/
            }

        });
    </script>

My JSON file is like this:

{
    "stationBeanList": [
        {
            "id": 72,
            "stationName": "W 52 St & 11 Ave",
            "availableDocks": 32,
            "totalDocks": 39,
            "latitude": 40.76727216,
            "longitude": -73.99392888,
            "statusValue": "In Service",
            "statusKey": 1,
            "availableBikes": 6,
            "stAddress1": "W 52 St & 11 Ave",
            "stAddress2": "",
            "city": "",
            "postalCode": "",
            "location": "",
            "altitude": "",
            "testStation": false,
            "lastCommunicationTime": null,
            "landMark": ""
        }
}

Thank you for your help!

1

1 Answer 1

0

You need to Iterate over each station in the array and return - given a set of starting lat/lng coordinates, and the station's own set of lat/lng coordinates - the distance between the two pairs. I've used this algorithm to good effect.

For convenience I've pared the station data down to minimum, and introduced a couple of addition stations. I made up the coordinates for each.

// Station dataset, and the the coordinates
// that we want to measure from
const stations={stationBeanList:[{id:72,stationName:"W 52 St & 11 Ave",availableDocks:32,totalDocks:39,latitude:40.76727216,longitude:-73.99392888,availableBikes:7},{id:76,stationName:"1st & Houston",availableDocks:23,totalDocks:30,latitude:41.76727216,longitude:-74.99392888,availableBikes:7},{id:12,stationName:"White plains",availableDocks:12,totalDocks:22,latitude:51.76727216,longitude:1.99392888,availableBikes:10}]};    const locationLat = 40.72730240765651;
const locationLng = -73.9939667324035;

// Our key distance function which takes in the coordinates
// from our current position, a set of station coordinates,
// and a unit of measurement (KM or M)
function getDistance(lat1, lon1, lat2, lon2, unit = 'M') {
  
  const R = 6371e3; // metres
  const φ1 = lat1 * Math.PI/180; // φ, λ in radians
  const φ2 = lat2 * Math.PI/180;
  const Δφ = (lat2-lat1) * Math.PI/180;
  const Δλ = (lon2-lon1) * Math.PI/180;

  const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
            Math.cos(φ1) * Math.cos(φ2) *
            Math.sin(Δλ/2) * Math.sin(Δλ/2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

  const d = R * c; // in metres

  if (unit === 'km') return d * 0.001;
  if (unit === 'mi') return d * 0.0006213712;

}

// This function accepts the initial coordinates, the stations list
// and the unit of measurement
function getStationDistances(locLat, locLng, stationsList, unit = 'mi') {
  
  // Iterate over the stations list using `map` which
  // will return a new array of objects
  return stationsList.map(station => {
    
    // For each station destructure the properties we
    // want to process (and return)
    const {
      id,
      stationName: name,
      latitude: sLat,
      longitude: sLng,
      availableDocks
    } = station; 
    
    // Pass the initial coordinates, the stations coordinates, and
    // a unit of measurement into the `getDistance` function.
    // Set the resulting value to two decimal places, and then
    // parse it back to a floating-point number
    const distance = Number.parseFloat((Math.round(getDistance(
      locLat,
      locLng,
      sLat,
      sLng,
      unit) * 100) / 100).toFixed(2));
    
    // In this example we're returning the station id, name,
    // the distance from the initial location, the unit of
    // measurement, its coordinates, and its available docks.
    return {
      id,
      name,
      distance,
      unit,
      sLat,
      sLng,
      availableDocks
    };
  
  // Finally we're sorting the returned array of objects by
  // distance starting with the nearest one
  }).sort((a, b) => a.distance > b.distance);

}

console.log(getStationDistances(locationLat, locationLng, stations.stationBeanList, 'mi'));

4
  • How can I obtain locationLng and locationLat from an input or from L.Routing.control({waypoint: [ ] } )? Can I use directly the JSON file without creating the "stations" list?
    – tommy
    Commented May 29, 2023 at 13:46
  • How can recall the function every time that I insert a new Starting and ending point?
    – tommy
    Commented May 30, 2023 at 14:51
  • Hi @tommy you should really ask a new question on the site for these as the code I've provided answers the immediate problem of how to get the distance between two sets of coordinates that you asked for. Plus, there are lots of other people here that can help with a new question that won't see these comments re additional functionality.
    – Andy
    Commented May 30, 2023 at 14:57
  • Ok, I didn't know that. Thank you for your help, I have fixed it. When I will finish the code I will post it on GitHub.
    – tommy
    Commented May 31, 2023 at 8:56

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