How to calculate the distance from a known point to the closest point in a route using Google Maps API

前端 未结 1 1139
隐瞒了意图╮
隐瞒了意图╮ 2021-01-07 08:38

I am working on a project that displays a map with multiple routes. I need to be able to search by an address and return the distance to the closest point within each of the

1条回答
  •  迷失自我
    2021-01-07 09:29

    One solution:

    1. extract the polylines from each route
    2. process through each of the polylines, finding the closest point (using the straight line, "as the crow flies" distance)
    // Use this new renderer with the result
    renderArray[i].setDirections(result);
    // and start the next request
    var polyline = getPolyline(result);
    var marker = new google.maps.Marker({
        position: getClosestPoint(referencePt, polyline),
        map: map,
        icon: iconArray[i]
    });
    nextRequest();
    

    proof of concept fiddle

    code snippet:

    var referencePt = "TBD";
    
    // Initialize some variables
    var directionsService = new google.maps.DirectionsService();
    var num, map, data;
    var requestArray = [],
      renderArray = [];
    var markerBounds = new google.maps.LatLngBounds();
    
    // A JSON Array containing some people/routes and the destinations/stops
    var jsonArray = {
      "Blue Run": ["300 University Ave, Plant 1 Belleville, ON K8N 5T7", "3900 West Hamlin Road Rochester Hills, MI 48309"],
      "Big Run": ["5811 - 99th Avenue Kenosha, WI 53144", "46600 Port St Plymouth, MI 48170"],
      "Slow Run": ["2155 North Talbot Road Windsor, ON N9A 6J3", "46600 Port St Plymouth, MI 48170", "2968 Waterview Rochester Hills, MI 48309", "4350 Campground Rd Louisville, KY 40216"]
    }
    
    // 16 Standard Colours for navigation polylines
    var colourArray = ['navy', 'red', 'green', 'grey', 'fuchsia', 'black', 'white', 'lime', 'maroon', 'purple', 'aqua', 'silver', 'olive', 'blue', 'yellow', 'teal'];
    
    var iconArray = [
      "http://maps.google.com/mapfiles/ms/icons/blue.png",
      "http://maps.google.com/mapfiles/ms/icons/red.png",
      "http://maps.google.com/mapfiles/ms/icons/green.png"
    ];
    
    // Let's make an array of requests which will become individual polylines on the map.
    function generateRequests() {
    
      requestArray = [];
    
      for (var route in jsonArray) {
        // This now deals with one of the people / routes
    
        // Somewhere to store the wayoints
        var waypts = [];
    
        // 'start' and 'finish' will be the routes origin and destination
        var start, finish
    
        // lastpoint is used to ensure that duplicate waypoints are stripped
        var lastpoint
    
        data = jsonArray[route]
    
        limit = data.length
        for (var waypoint = 0; waypoint < limit; waypoint++) {
          if (data[waypoint] === lastpoint) {
            // Duplicate of of the last waypoint - don't bother
            continue;
          }
    
          // Prepare the lastpoint for the next loop
          lastpoint = data[waypoint]
    
          // Add this to waypoint to the array for making the request
          waypts.push({
            location: data[waypoint],
            stopover: true
          });
        }
    
        // Grab the first waypoint for the 'start' location
        start = (waypts.shift()).location;
        // Grab the last waypoint for use as a 'finish' location
        finish = waypts.pop();
        if (finish === undefined) {
          // Unless there was no finish location for some reason?
          finish = start;
        } else {
          finish = finish.location;
        }
    
        // Let's create the Google Maps request object
        var request = {
          origin: start,
          destination: finish,
          waypoints: waypts,
          travelMode: google.maps.TravelMode.DRIVING
        };
    
        // and save it in our requestArray
        requestArray.push({
          "route": route,
          "request": request
        });
      }
    
      processRequests();
    }
    
    function processRequests() {
    
      // Counter to track request submission and process one at a time;
      var i = 0;
    
      // Used to submit the request 'i'
      function submitRequest() {
        directionsService.route(requestArray[i].request, directionResults);
      }
    
      // Used as callback for the above request for current 'i'
      function directionResults(result, status) {
        if (status == google.maps.DirectionsStatus.OK) {
    
          // Create a unique DirectionsRenderer 'i'
          renderArray[i] = new google.maps.DirectionsRenderer();
          renderArray[i].setMap(map);
    
          // Some unique options from the colorArray so we can see the routes
          renderArray[i].setOptions({
            preserveViewport: true,
            suppressInfoWindows: true,
            polylineOptions: {
              strokeWeight: 4,
              strokeOpacity: 0.8,
              strokeColor: colourArray[i]
            },
            markerOptions: {
              icon: {
                path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
                scale: 4,
                strokeColor: colourArray[i]
              },
              clickable: true,
              title: 'Boo yeah!'
            }
          });
    
          // Use this new renderer with the result
          renderArray[i].setDirections(result);
          // and start the next request
          var polyline = getPolyline(result);
          var marker = new google.maps.Marker({
            position: getClosestPoint(referencePt, polyline),
            map: map,
            icon: iconArray[i]
          });
          markerBounds.extend(marker.getPosition());
          nextRequest();
        }
    
      }
    
      function nextRequest() {
        // Increase the counter
        i++;
        // Make sure we are still waiting for a request
        if (i >= requestArray.length) {
          map.fitBounds(markerBounds);
          // No more to do
          return;
        }
        // Submit another request
        submitRequest();
      }
    
      // This request is just to kick start the whole process
      submitRequest();
    }
    
    function getPolyline(result) {
      var polyline = new google.maps.Polyline({
        path: []
      });
      var path = result.routes[0].overview_path;
      var legs = result.routes[0].legs;
      for (i = 0; i < legs.length; i++) {
        var steps = legs[i].steps;
        for (j = 0; j < steps.length; j++) {
          var nextSegment = steps[j].path;
          for (k = 0; k < nextSegment.length; k++) {
            polyline.getPath().push(nextSegment[k]);
          }
        }
      }
      return polyline;
    }
    
    function getClosestPoint(point, polyline) {
      var closestDistance = Number.MAX_VALUE;
      var closestPt;
      for (var i = 0; i < polyline.getPath().getLength(); i++) {
        var distance = google.maps.geometry.spherical.computeDistanceBetween(point, polyline.getPath().getAt(i));
        if (distance < closestDistance) {
          closestDistance = distance;
          closestPt = polyline.getPath().getAt(i);
        }
      }
      return closestPt;
    }
    
    // Called Onload
    function init() {
    
      var address = "320 Elizabeth St Midland, ON L4R 4L6";
      var geo = new google.maps.Geocoder;
      geo.geocode({
        'address': address
      }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          var latitude = results[0].geometry.location.lat();
          var longitude = results[0].geometry.location.lng();
    
          // Some basic map setup (from the API docs) 
          var mapOptions = {
            //center: new google.maps.LatLng(50.677965, -3.768841),
            center: new google.maps.LatLng(latitude, longitude),
            zoom: 10,
            mapTypeControl: true,
            streetViewControl: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            travelMode: google.maps.TravelMode.DRIVING,
            //unitSystem: google.maps.UnitSystem.IMPERIAL
            unitSystem: google.maps.UnitSystem.METRIC
          };
    
          map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
    
          var circle = {
            strokeColor: '#AA0000',
            strokeOpacity: 0.6,
            strokeWeight: 2,
            fillColor: '#CCCCCC',
            fillOpacity: 0.35,
            map: map,
            radius: 50000,
            center: new google.maps.LatLng(latitude, longitude)
          };
          referencePt = mapOptions.center;
    
          var pickupSpot = new google.maps.Circle(circle);
    
          // Start the request making
          generateRequests()
        } else {
          alert("Geocode was not successful for the following reason: " + status);
        }
      });
    }
    
    // Get the ball rolling and trigger our init() on 'load'
    google.maps.event.addDomListener(window, 'load', init);
    html,
    body,
    #map-canvas {
      height: 100%;
      margin: 0px;
      padding: 0px
    }
    #map-canvas {
      float: left;
      width: 70%;
      height: 100%;
    }
    #panel {
      position: absolute;
      top: 5px;
      left: 50%;
      margin-left: -180px;
      z-index: 5;
      background-color: #fff;
      padding: 5px;
      border: 1px solid #999;
    }
    #control_panel {
      float: right;
      width: 30%;
      text-align: left;
      padding-top: 20px;
    }
    
    

    Trips:

    Blue Run

    1. Autosystems (University)
      300 University Ave, Plant 1 Belleville, ON K8N 5T7
    2. Fanuc America
      3900 West Hamlin Road Rochester Hills, MI 48309

    Big Run

    1. Asyst Technologies
      5811 - 99th Avenue Kenosha, WI 53144
    2. Autosystems America Inc
      46600 Port St Plymouth, MI 48170

    Slow Run

    1. A B Automation
      2155 North Talbot Road Windsor, ON N9A 6J3
    2. Autosystems America Inc
      46600 Port St Plymouth, MI 48170
    3. Industrial Automation
      2968 Waterview Rochester Hills, MI 48309
    4. Arkema Inc.
      4350 Campground Rd Louisville, KY 40216

    0 讨论(0)
提交回复
热议问题