【问题标题】:Driving distance area行驶距离区域
【发布时间】:2012-11-10 00:32:32
【问题描述】:

有没有办法通过 Google Maps API 在给定中心点的给定行驶时间内确定边界多边形?

如果做不到这一点,有没有一种方法可以计算驾驶时间函数的倒数——也就是说,不是“从 A 点到 B 点需要多少分钟”,而是一种询问“多远我会在一定分钟内从 A 点到达 B 点吗?”当然,我可以只找到点之间的时间并假设天真的缩放,但如果速度限制在路线的重要部分有很大差异,那可能还有一段路要走。

【问题讨论】:

    标签: google-maps-api-3


    【解决方案1】:

    注意:由于 Google 的政策变更,这些示例不再有效(You have exceeded your request quota for this API. 错误),将 API 密钥替换为有效的密钥即可)

    代码 sn-p:

    var map;
    var container;
    var zoom = 9;
    var centerPoint = new google.maps.LatLng(35.149534, -90.04898);
    var dirService = new google.maps.DirectionsService();
    var centerMarker;
    var circleMarkers = Array();
    var circlePoints = Array();
    var drivePolyPoints = Array();
    var searchPolygon, drivePolygon;
    var distToDrive = 30; // miles
    var pointInterval = 30;
    var searchPoints = [];
    var polyline;
    var polylines = [];
    var redIcon8 = "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png";
    
    function initialize() {
      map = new google.maps.Map(
        document.getElementById("map_canvas"), {
          center: centerPoint,
          zoom: 9,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        });
      google.maps.event.addListener(map, "click", mapClick);
    }
    google.maps.event.addDomListener(window, "load", initialize);
    
    function mapClick(evt) {
      // map.clearOverlays();
      circleMarkers = Array();
      if (!centerMarker) {
        centerMarker = new google.maps.Marker({
          position: evt.latLng,
          map: map
        });
      } else {
        centerMarker.setMap(null);
        centerMarker.setPosition(evt.latLng);
      }
      centerMarker.setMap(map);
      searchPoints = getCirclePoints(evt.latLng, distToDrive);
      drivePolyPoints = Array();
      getDirections();
    }
    
    function getCirclePoints(center, radius) {
      var bounds = new google.maps.LatLngBounds();
      var circlePoints = Array();
      var searchPoints = Array();
      with(Math) {
        var rLat = (radius / 3963.189) * (180 / PI); // miles
        var rLng = rLat / cos(center.lat() * (PI / 180));
        for (var a = 0; a < 361; a++) {
          var aRad = a * (PI / 180);
          var x = center.lng() + (rLng * cos(aRad));
          var y = center.lat() + (rLat * sin(aRad));
          var point = new google.maps.LatLng(parseFloat(y), parseFloat(x), true);
          bounds.extend(point);
          circlePoints.push(point);
          if (a % pointInterval == 0) {
            searchPoints.push(point);
          }
        }
      }
      searchPolygon = new google.maps.Polygon({
        paths: circlePoints,
        strokeColor: '#0000ff',
        strokeWeight: 1,
        strokeOpacity: 1,
        fillColor: '#0000ff',
        fillOpacity: 0.2
      });
      searchPolygon.setMap(map);
      map.fitBounds(bounds);
      return searchPoints;
    }
    
    function getDirections() {
      if (!searchPoints.length) {
        return;
      }
      var to = searchPoints.shift();
      var request = {
        origin: centerMarker.getPosition(),
        destination: to,
        travelMode: google.maps.TravelMode.DRIVING
      };
      dirService.route(request, function(result, status) {
        if (status == google.maps.DirectionsStatus.OK) {
          var distance = parseInt(result.routes[0].legs[0].distance.value / 1609);
          var duration = parseFloat(result.routes[0].legs[0].duration.value / 3600).toFixed(2);
          var path = result.routes[0].overview_path;
          var legs = result.routes[0].legs;
          if (polyline && polyline.setPath) {
            polyline.setPath([]);
          } else {
            polyline = new google.maps.Polyline({
              path: [],
              // map: map,
              strokeColor: "#FF0000",
              strokeOpacity: 1
            });
          }
          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]);
                // bounds.extend(nextSegment[k]);
              }
            }
          }
          // polyline.setMap(map);
          shortenAndShow(polyline);
          getDirections();
        } else {
          console.log("Directions request failed, status=" + status + " [from:" + request.origin + " to:" + request.destination + "]");
          getDirections();
        }
      });
    }
    
    function shortenAndShow(polyline) {
      var distToDriveM = distToDrive * 1609;
      var dist = 0;
      var cutoffIndex = 0;
      var copyPoints = Array();
      for (var n = 0; n < polyline.getPath().getLength() - 1; n++) {
        dist += google.maps.geometry.spherical.computeDistanceBetween(polyline.getPath().getAt(n), polyline.getPath().getAt(n + 1));
        //GLog.write(dist + ' - ' + distToDriveM);
        if (dist < distToDriveM) {
          copyPoints.push(polyline.getPath().getAt(n));
        } else {
          break;
        }
      }
      var lastPoint = copyPoints[copyPoints.length - 1];
      var newLine = new google.maps.Polyline({
        path: copyPoints,
        strokeColor: '#ff0000',
        strokeWeight: 2,
        strokeOpacity: 1
      });
      newLine.setMap(map);
      polylines.push(newLine);
      drivePolyPoints.push(lastPoint);
      addBorderMarker(lastPoint, dist)
      if (drivePolyPoints.length > 3) {
        if (drivePolygon) {
          drivePolygon.setMap(null);
        }
        drivePolygon = new google.maps.Polygon({
          paths: drivePolyPoints,
          strokeColor: '#00ff00',
          strokeWeight: 1,
          strokeOpacity: 1,
          fillColor: '#00ff00',
          fillOpacity: 0.4
        });
        drivePolygon.setMap(map);
      }
    }
    
    function addBorderMarker(pt, d) {
      var str = pt.lat().toFixed(6) + ',' + pt.lng().toFixed(6) + ' - Driving Distance: ' + (d / 1609).toFixed(2) + ' miles';
      var marker = new google.maps.Marker({
        position: pt,
        icon: redIcon8,
        title: str
      });
      circleMarkers.push(marker);
      marker.setMap(map);
    }
    
    function clearOverlays() {
      for (var i = 0; i < circleMarkers.length; i++) {
        circleMarkers[i].setMap(null);
      }
      circleMarkers = [];
      for (var i = 0; i < circlePoints.length; i++) {
        circlePoints[i].setMap(null);
      }
      circlePoints = [];
      for (var i = 0; i < polylines.length; i++) {
        polylines[i].setMap(null);
      }
      polylines = [];
      if (searchPolygon && searchPolygon.setMap) searchPolygon.setMap(null);
      if (drivePolygon && drivePolygon.setMap) drivePolygon.setMap(null);
      if (centerMarker && centerMarker.setMap) centerMarker.setMap(null);
    }
    html,
    body,
    #map_canvas {
      height: 100%;
      width: 100%;
      margin: 0px;
      padding: 0px
    }
    <a href="#" onclick="clearOverlays();">Clear</a>&nbsp;|&nbsp;
    <a href="#" onclick="pointInterval=30;clearOverlays();">interval 30 (default)</a>&nbsp;|&nbsp;
    <a href="#" onclick="pointInterval=20;clearOverlays();">interval 20</a>&nbsp;|&nbsp;
    
    <script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
    <div id="map_canvas"></div>

    【讨论】:

      【解决方案2】:

      几年前我创建了this driving radius demo,但它使用了现在已弃用的 API V2。您只需要将其转换为 V3。

      【讨论】:

      • 此链接已损坏
      【解决方案3】:

      我知道这个问题已经 8 年前了,但它很有帮助,这里是演示的小提琴链接,因为上面的所有链接都不起作用。 Fiddle Demo

      您只需要自己更改 API KEY,而且我已将单位从英里更改为公里。

      <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key={API_KEY}"></script>
      

      【讨论】:

      • 您是否进行了任何更改?你的小提琴也不起作用,我不确定另一个链接到非工作示例的价值是什么(我的例子的问题是关键,用活动键替换它,它们会起作用,因为我假设你发现)
      • 是的,我只是将单位从英里更改为公里,我只是复制粘贴代码并使用我的 api 密钥
      猜你喜欢
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 2013-07-01
      相关资源
      最近更新 更多