【问题标题】:How can I determine the location along a given route using mileage? [duplicate]如何使用里程确定给定路线上的位置? [复制]
【发布时间】:2021-01-21 01:11:54
【问题描述】:

例如,给定一条迈阿密和纽约之间的路线(驾车),我想计算出在同一条路线上经过几英里后某个位置的纬度/经度。

Google 的 API 是否提供了使用给定路线查找位置并询问距离该路线几英里的位置?

【问题讨论】:

    标签: google-maps


    【解决方案1】:

    相关问题:

    用途 http://www.geocodezip.com/scripts/v3_epoly.js

    Mike Williams 为 Google Maps Javascript API v2 编写的第三方库,已移植到 v3。
    Documentation for the v2 version

    有这个方法:

    • .GetPointAtDistance() 在指定距离处返回LatLng 沿着路径。 距离以米为单位 如果路径短于该路径,则返回 null

    live example

    代码 sn-p:

    var directionDisplay;
    var directionsService = new google.maps.DirectionsService();
    var map;
    var polyline = null;
    var marker;
    var infowindow;
    
    function createMarker(latlng, label, html) {
      var contentString = '<b>' + label + '</b><br>' + html;
      var marker = new google.maps.Marker({
        position: latlng,
        map: map,
        title: label,
        zIndex: Math.round(latlng.lat() * -100000) << 5,
        contentString: contentString
      });
      marker.myname = label;
      // gmarkers.push(marker);
    
      google.maps.event.addListener(marker, 'click', function() {
        infowindow.setContent(this.contentString);
        infowindow.open(map, marker);
      });
      return marker;
    }
    var myLatLng = null;
    var lat;
    var lng;
    var zoom = 2;
    var maptype;
    
    function initialize() {
      infowindow = new google.maps.InfoWindow();
      myLatLng = new google.maps.LatLng(37.422104808, -122.0838851);
      maptype = google.maps.MapTypeId.ROADMAP;
      var myOptions = {
        zoom: zoom,
        center: myLatLng,
        mapTypeId: maptype
      };
      directionsDisplay = new google.maps.DirectionsRenderer({
        suppressMarkers: true
      });
    
      map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
      polyline = new google.maps.Polyline({
        path: [],
        strokeColor: '#FF0000',
        strokeWeight: 3
      });
      directionsDisplay.setMap(map);
      calcRoute();
    }
    
    function calcRoute() {
    
      var start = document.getElementById("start").value;
      var end = document.getElementById("end").value;
      var travelMode = google.maps.DirectionsTravelMode.DRIVING
    
      var request = {
        origin: start,
        destination: end,
        travelMode: travelMode
      };
      directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
          polyline.setPath([]);
          var bounds = new google.maps.LatLngBounds();
          startLocation = new Object();
          endLocation = new Object();
          directionsDisplay.setDirections(response);
          var route = response.routes[0];
          var summaryPanel = document.getElementById("directions_panel");
          summaryPanel.innerHTML = "";
    
          // For each route, display summary information.
          var path = response.routes[0].overview_path;
          var legs = response.routes[0].legs;
          for (i = 0; i < legs.length; i++) {
            if (i == 0) {
              startLocation.latlng = legs[i].start_location;
              startLocation.address = legs[i].start_address;
            }
            endLocation.latlng = legs[i].end_location;
            endLocation.address = legs[i].end_address;
            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]);
                bounds.extend(nextSegment[k]);
              }
            }
          }
    
          polyline.setMap(map);
    
          computeTotalDistance(response);
          putMarkerOnRoute(parseFloat(document.getElementById('distance').value));
        } else {
          alert("directions response " + status);
        }
      });
    }
    
    var totalDist = 0;
    var totalTime = 0;
    
    function computeTotalDistance(result) {
      totalDist = 0;
      totalTime = 0;
      var myroute = result.routes[0];
      for (i = 0; i < myroute.legs.length; i++) {
        totalDist += myroute.legs[i].distance.value;
        totalTime += myroute.legs[i].duration.value;
      }
      totalDist = totalDist / 1000.
      document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes<br>average speed is: " + (totalDist / (totalTime / 3600)).toFixed(2) + " kph";
      document.getElementById("totalTime").value = (totalTime / 60.).toFixed(2);
    }
    
    function putMarkerOnRoute(distance) {
      if (distance > totalDist)
        distance = totalDist;
      time = distance / totalDist * totalTime / 60;
      if (!marker) {
        marker = createMarker(polyline.GetPointAtDistance(distance * 1000), "distance: " + distance, "marker");
      } else {
        marker.setPosition(polyline.GetPointAtDistance(distance * 1000));
        marker.setTitle("time:" + time.toFixed(2));
        marker.contentString = "<b>time: " + time.toFixed(2) + "</b><br>distance: " + (distance).toFixed(2) + " km<br>marker";
        google.maps.event.trigger(marker, "click");
      }
    }
    google.maps.event.addDomListener(window, 'load', initialize);
    // from v3_epoly.js
    // === A method which returns a GLatLng of a point a given distance along the path ===
    // === Returns null if the path is shorter than the specified distance ===
    google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
      // some awkward special cases
      if (metres == 0) return this.getPath().getAt(0);
      if (metres < 0) return null;
      if (this.getPath().getLength() < 2) return null;
      var dist = 0;
      var olddist = 0;
      for (var i = 1;
        (i < this.getPath().getLength() && dist < metres); i++) {
        olddist = dist;
        dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
      }
      if (dist < metres) {
        return null;
      }
      var p1 = this.getPath().getAt(i - 2);
      var p2 = this.getPath().getAt(i - 1);
      var m = (metres - olddist) / (dist - olddist);
      return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
    }
    html {
      height: 100%
    }
    
    body {
      height: 100%;
      margin: 0px;
      padding: 0px
    }
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry&v=weekly"></script>
    <div id="tools">
      start:
      <input type="text" name="start" id="start" value="Hyderabad" /> end:
      <input type="text" name="end" id="end" value="Bangalore" />
      <input type="submit" onclick="calcRoute();" /><br /> distance:
      <input type="text" name="distance" id="distance" value="100" />
      <input type="submit" onclick="putMarkerOnRoute(parseFloat(document.getElementById('distance').value));" /> &nbsp;total time:<input type="text" name="totalTime" id="totalTime" value="0" />
    </div>
    <div id="map_canvas" style="float:left;width:70%;height:80%;"></div>
    <div id="control_panel" style="float:right;width:30%;text-align:left;padding-top:20px">
      <div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div>
      <div id="total"></div>

    【讨论】:

    • 虽然我认为这没有考虑到可变速度限制,谷歌可能会在计算穿越多条高速公路/道路的路线的行驶持续时间时包含这些限制
    • 不,这只是一个直线比例。您可以向路线服务提出额外请求以获得更好的估计。
    猜你喜欢
    • 2012-12-06
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多