javascript - 通过谷歌地图上的经纬度数组获取距离

标签 javascript jquery google-maps google-maps-api-3

var path = [
    { "lat": 43.00678, "lng": -89.53743 },
    { "lat": 43.00656, "lng": -89.53732 },
    { "lat": 43.005878, "lng": -89.53797 },
    { "lat": 43.005344, "lng": -89.53684 },
    { "lat": 43.003834, "lng": -89.535400 },
    { "lat": 43.003692, "lng": -89.533834 },
    { "lat": 43.006384, "lng": -89.533796 },
    { "lat": 43.0120328, "lng": -89.533667 },
    { "lat": 43.015931, "lng": -89.533635 },
    { "lat": 43.023030, "lng": -89.5335390 },
    { "lat": 43.032010, "lng": -89.533249 },
    { "lat": 43.040221, "lng": -89.5329596 },
    { "lat": 43.04632176, "lng": -89.5318224 },
    { "lat": 43.052562, "lng": -89.5277883 },
    { "lat": 43.060300, "lng": -89.52759526 },
    { "lat": 43.06401556, "lng": -89.5268978 },
    { "lat": 43.06681381, "lng": -89.5241620 },
    { "lat": 43.0714224, "lng": -89.52499888 },
    { "lat": 43.07468269, "lng": -89.52698371 },
    { "lat": 43.07490213, "lng": -89.53292749 },
    { "lat": 43.076203059, "lng": -89.53269145 },
    { "lat": 43.0765949, "lng": -89.5314576 },
    { "lat": 43.0793377, "lng": -89.53323862 },
    { "lat": 43.0803799, "lng": -89.53454754 },
    { "lat": 43.0835927, "lng": -89.5340754 },
    { "lat": 43.08458789, "lng": -89.5334853 },
    { "lat": 43.0844468, "lng": -89.53403256 },
    { "lat": 43.08445469, "lng": -89.5352985 },
    { "lat": 43.084619242, "lng": -89.5358993791 }
];

这是 Javascript 数组,我想在谷歌地图上绘制一条折线用于车辆跟踪并找到车辆行程的总距离

最佳答案

计算路径总距离最简单的方法是遍历路径数组并计算每个点之间的距离 Haversine formula: https://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula或与 google.maps.geometry.spherical.computeDistanceBetween(latLngA, latLngB); 方法并总结结果。 (后一种情况您必须加载几何库:https://maps.googleapis.com/maps/api/js?libraries=geometry) 例如:

function calcPathLength(path){
    var total = 0;
    for (var i = 0; i < path.length - 1; i++) {
        var pos1 = new google.maps.LatLng(path[i].lat(), path[i].lng());
        var pos2 = new google.maps.LatLng(path[i + 1].lat(), path[i + 1].lng());
        total += google.maps.geometry.spherical.computeDistanceBetween(pos1, pos2);
    };
    return total;
};

这只给你一个近似的结果,因为两点之间的距离有时太大,路径不会精确地遵循道路。

解决此问题的另一种方法是使用 Google Maps Roads API snap to roads feature. (https://developers.google.com/maps/documentation/roads/snap)在这种情况下,我们仍然有点之间距离的问题,因为文档说连续的点对应该在 300m 以内。我认为我们能做的最好的事情就是在路径中添加更多点。 在下面的示例中,我将向您展示如何显示和计算路径的总距离。为了您的目的,我修改了谷歌的 Snap to Road 演示。请注意,道路 API 需要 API key ,因此您应将 YOUR_API_KEY 替换为您的 key 。

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Roads API Demo</title>
    <style>
      html, body, #map {
        height: 100%;
        margin: 0px;
        padding: 0px
      }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script
      src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
    <script>
var apiKey = 'YOUR_API_KEY'; //Replace it with your key
            //This is the path you provided
var path = [
    { "lat": 43.00678, "lng": -89.53743 },
    { "lat": 43.00656, "lng": -89.53732 },
    { "lat": 43.005878, "lng": -89.53797 },
    { "lat": 43.005344, "lng": -89.53684 },
    { "lat": 43.003834, "lng": -89.535400 },
    { "lat": 43.003692, "lng": -89.533834 },
    { "lat": 43.006384, "lng": -89.533796 },
    { "lat": 43.0120328, "lng": -89.533667 },
    { "lat": 43.015931, "lng": -89.533635 },
    { "lat": 43.023030, "lng": -89.5335390 },
    { "lat": 43.032010, "lng": -89.533249 },
    { "lat": 43.040221, "lng": -89.5329596 },
    { "lat": 43.04632176, "lng": -89.5318224 },
    { "lat": 43.052562, "lng": -89.5277883 },
    { "lat": 43.060300, "lng": -89.52759526 },
    { "lat": 43.06401556, "lng": -89.5268978 },
    { "lat": 43.06681381, "lng": -89.5241620 },
    { "lat": 43.0714224, "lng": -89.52499888 },
    { "lat": 43.07468269, "lng": -89.52698371 },
    { "lat": 43.07490213, "lng": -89.53292749 },
    { "lat": 43.076203059, "lng": -89.53269145 },
    { "lat": 43.0765949, "lng": -89.5314576 },
    { "lat": 43.0793377, "lng": -89.53323862 },
    { "lat": 43.0803799, "lng": -89.53454754 },
    { "lat": 43.0835927, "lng": -89.5340754 },
    { "lat": 43.08458789, "lng": -89.5334853 },
    { "lat": 43.0844468, "lng": -89.53403256 },
    { "lat": 43.08445469, "lng": -89.5352985 },
    { "lat": 43.084619242, "lng": -89.5358993791 }
  ]; 
var map;
var snappedCoordinates = [];
var extendedPath = [];
var startMarker;
var endMarker;
var startIcon = 'https://mts.googleapis.com/maps/vt/icon/name=icons/spotlight/spotlight-waypoint-a.png&text=A&psize=16&font=fonts/Roboto-Regular.ttf&color=ff333333&ax=44&ay=48&scale=1';
var endIcon = 'https://mts.googleapis.com/maps/vt/icon/name=icons/spotlight/spotlight-waypoint-b.png&text=B&psize=16&font=fonts/Roboto-Regular.ttf&color=ff333333&ax=44&ay=48&scale=1';
var infowindow;
function initialize() {
  var mapOptions = {
    zoom: 12,
    center: {lat: 43.040221, lng: -89.5329596}
  };
  map = new google.maps.Map(document.getElementById('map'), mapOptions);
  startMarker = new google.maps.Marker({
    map: map,
    position: new google.maps.LatLng(path[0].lat, path[0].lng),
    icon: startIcon
  });
  endMarker = new google.maps.Marker({
    map: map,
    position: new google.maps.LatLng(path[path.length - 1].lat, path[path.length - 1].lng),
    icon: endIcon
  })
  infowindow = new google.maps.InfoWindow({content: ''});
  extendedPath = getExtendedPath(path); //Let's extend the original path
  runSnapToRoad(extendedPath);
}
function getExtendedPath(path) {
  var extPath = path;
  var newPath = [];
  while (pointsTooFar(extPath)){  //We do it while all the distance between points are less then 250 meters
      newPath = [];
      for (var i = 0; i < extPath.length - 1; i++) {
        var pos1 = new google.maps.LatLng(extPath[i].lat, extPath[i].lng);
        var pos2 = new google.maps.LatLng(extPath[i + 1].lat, extPath[i + 1].lng);
        var dist = google.maps.geometry.spherical.computeDistanceBetween(pos1, pos2);
        newPath.push(extPath[i]);
        if (dist > 250) {  //If the distance between two points is greater than 250 metres we add an intermediate point 
           var insPos = { "lat": (extPath[i].lat + extPath[i + 1].lat)/2, "lng": (extPath[i].lng + extPath[i + 1].lng)/2 };
            newPath.push(insPos);
        }
      }
      newPath.push(extPath[extPath.length-1]);
      extPath = newPath;
  }
  return extPath;
}

function pointsTooFar(pointPath){
  var tooFar = false;
  for (var i = 0; i < pointPath.length - 1; i++) {
    var pos1 = new google.maps.LatLng(pointPath[i].lat, pointPath[i].lng);
    var pos2 = new google.maps.LatLng(pointPath[i + 1].lat, pointPath[i + 1].lng);
    var dist = google.maps.geometry.spherical.computeDistanceBetween(pos1, pos2);
    if (dist > 250){
        tooFar = true;
        break;
    };
  }; 
  return tooFar;
}

// Snap a user-created polyline to roads and draw the snapped path
function runSnapToRoad(path) {
  var pathValues = [];
  for (var i = 0; i < path.length; i++) {
    pathValues.push((new google.maps.LatLng(path[i].lat, path[i].lng)).toUrlValue());
  }
  $.get('https://roads.googleapis.com/v1/snapToRoads', {
    interpolate: true,
    key: apiKey,
    path: pathValues.join('|')
  }, function(data) {
    processSnapToRoadResponse(data);
    drawSnappedPolyline();
    calcPathLength(snappedCoordinates);
  });
}

// Store snapped polyline returned by the snap-to-road service.
function processSnapToRoadResponse(data) {
  snappedCoordinates = [];
  for (var i = 0; i < data.snappedPoints.length; i++) {
    var latlng = new google.maps.LatLng(
        data.snappedPoints[i].location.latitude,
        data.snappedPoints[i].location.longitude);
    snappedCoordinates.push(latlng);
  }
}

// Draws the snapped polyline (after processing snap-to-road response).
function drawSnappedPolyline() {
  var snappedPolyline = new google.maps.Polyline({
    path: snappedCoordinates,
    strokeColor: '#00B3FD',
    strokeOpacity: 0.6,
    strokeWeight: 5
  });
  snappedPolyline.setMap(map);
}

function calcPathLength(cPath){
    var total = 0;
    for (var i = 0; i < cPath.length - 1; i++) {
        var pos1 = new google.maps.LatLng(cPath[i].lat(), cPath[i].lng());
        var pos2 = new google.maps.LatLng(cPath[i + 1].lat(), cPath[i + 1].lng());
        total += google.maps.geometry.spherical.computeDistanceBetween(pos1, pos2);
        console.log(google.maps.geometry.spherical.computeDistanceBetween(pos1, pos2).toFixed(0));
    };
    infowindow.setContent('<h4>Total length of the path: ' + (total / 1609.34).toFixed(1) + ' miles</h4>');
    infowindow.open(map, endMarker);
};

$(window).load(initialize);

    </script>
  </head>
  <body>
    <div id="map"></div>
  </body>
</html>

希望这对您有所帮助。

关于javascript - 通过谷歌地图上的经纬度数组获取距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38183201/

相关文章:

javascript - Google map 使用 AJAX 添加标记

javascript - 带有 ng-repeat 的 Angular 切换表行 ng-class

javascript - jQuery 未定义值

javascript - 我如何为 jqGrid 中的列赋值?

google-maps - map 空闲事件的监听器不适用于 Google map API v3.28.18

php - 试图找出一种从 Facebook 内部弹出 Google map 的方法

javascript - 在 Rails 中通过参数发送 base64 图像是一个好习惯吗?

javascript - ajaxToolkit AutoCompleteExtender Chrome 错误

javascript - 如何使用 jQuery click 方法显示隐藏的元素?

javascript - Jqplot栏的边距/边框颜色