计算地点之间的驾车距离

6

我已经成功地使用Maptiler API(OSMNames)为表单输入添加了自动完成功能(因为我发现Google Maps API更加令人困惑)。

现在出现了实际问题,我想要通过我创建的两个输入框中的自动完成功能获取两个地点之间的驾车距离。

我正在尝试使用OSRM(开源路由机器) API来实现这一目标。

以下是我的当前脚本:

<!--AUTOCOMPLETE-->
<script>
    var autocomplete = new kt.OsmNamesAutocomplete(
    'search1', 'https://geocoder.tilehosting.com/', '#My_Maptiler_API_Code');
</script>
<script>
    var autocomplete = new kt.OsmNamesAutocomplete(
    'search2', 'https://geocoder.tilehosting.com/', '#My_Maptiler_API_Code');
</script>

<!--GET INFO-->
<script>
    function loadXMLDoc() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById("result").innerHTML =
            this.responseText;
        }

        if (this.readyState == 4 && this.status == 429) {
            document.getElementById("result").innerHTML =
            "Server overloaded, please try again later."
        }
    };
    xhttp.open("GET", "http://router.project-osrm.org/table/v1/driving/{longitude1},{latitude1};{longitude2},{latitude2}", true);
    xhttp.send();
    }
</script>

首先,我需要通过使用autocomplete函数从inputs中获取地点的坐标。

当前,当用户点击建议列表中的一个地点时,只有name项会被写入input框。相反,我想要得到写有GPS坐标而不是name的文本,以便我可以用它们来发送HTTP请求(下一步)。

当我点击时正在被写入什么:

What is being written when I click

接下来我需要什么:

What I need for the next step

顺便说一下,我在其他相关问题的答案中看到有人邀请使用 "Nominatim"。正如我所说,我目前正在使用 "OSMNames",这有什么区别吗?我应该更改我的地理编码器吗?

然后,我还需要在HTTP GET请求中获取这些坐标,就像代码中显示的那样。

最后,我想从OSRM响应中只获取一个项目,即距离。否则,我将只获得整个响应。

我尽量避免在此处放置所有代码,因为我发现阅读时很混乱,但如果您出于任何原因需要其余代码,请告诉我!


你期望得到什么距离?是A点和B点之间的直线距离,还是实际驾驶距离?如果是前者,你可以使用每个点的纬度/经度和一些粗略的大圆计算来计算出相当不错的估计值。如果你需要驾驶距离,你首先需要计算路线并测量该路线,这要复杂得多,除非你已经有了一个路由算法。 - Javier Larroulet
哦,真的... 我在寻找行驶距离,并且我认为有免费的开源路由算法(易于实现:))。如果你们知道任何一个(这样我就可以使用它的文档并尝试实施),并且能够在这里分享,那就太好了。感谢您的帮助!Javier的问题非常感谢! :) - Agustín Suárez
2
不客气!如果您只需要点A和点B之间的驾车距离和时间,但不需要(或不想处理)驾车路线或自己计算这些内容,您可以通过Google的距离矩阵API获得所需的准确信息,但请注意,这不是免费解决方案。它将花费您大约5美元每1000个请求。其他解决方案可以在此OSM讨论线程这里找到。 - Javier Larroulet
好的!!非常非常感谢!!我会去看看OSRM的替代方案,看看我能做什么,我还在学习但这听起来很有趣。祝你有美好的一天!! - Agustín Suárez
1
OSRM 返回以米为单位的实际驾驶距离。float 只是数据类型。 - scai
非常感谢你!!!我现在会编辑我的问题! - Agustín Suárez
1个回答

0

来自2023年的问候!我为您创建了一个jsFiddle演示,其中使用Nominatim解析目标位置和OSRM表格服务计算到达该位置的距离:

Openstreetmap with Nominatim and OSRM

我的印象是,现在许多地理编码插件都没有得到很好的维护,所以我只使用jQuery来调用Nominatim,然后使用OSRM表服务:

'use strict';

function processOsrmReply(data) {
  console.log(data);

  if (data.code !== 'Ok') {
    $('#myHint').text('OSRM error code: ' + data.code);
    return;
  }

  $('#myHint').text('Distance: ' + data.distances);
}

function sendOsrmRequest(startLat, startLng, endLat, endLng) {

  var osrmUrl = 'https://router.project-osrm.org/table/v1/driving/' +
    parseFloat(startLng).toFixed(6) + ',' + parseFloat(startLat).toFixed(6) + ';' +
    parseFloat(endLng).toFixed(6) + ',' + parseFloat(endLat).toFixed(6);

  var osrmParams = {
    sources: 0,
    destinations: 1,
    annotations: 'distance'
  };

  $('#myHint').text('Calculating driving distance between places...');
  $.get(osrmUrl, osrmParams, processOsrmReply);
}

var startPosition = [51.4661, 7.2491];
var myMap = L.map('myMap').setView(startPosition, 13);

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

var startMarker = L.marker(startPosition)
  .bindPopup('Start: ' + startPosition)
  .addTo(myMap);

$('#myInput').autocomplete({
  source: function(request, response) {

    var nominatimUrl = 'https://nominatim.openstreetmap.org/search/';

    var nominatimParams = {
      q: request.term,
      format: 'json',
      addressdetails: 1,
      limit: 2,
      polygon_geojson: 1
    };

    $.get(nominatimUrl, nominatimParams, function(data) {
      console.log(data);

      if (data.length === 0) {
        $('#myHint').text('Nominatim returned nothing');
        return;
      }

      var autocompleteParams = data.map(n => {
        return {
          label: n.display_name,
          value: [n.lat, n.lon]
        }
      });

      response(autocompleteParams);
    });
  },
  minLength: 5,
  select: function(event, ui) {
    var finalPosition = ui.item.value;
    var finalMarker = L.marker(finalPosition)
      .bindPopup('Destination: ' + finalPosition)
      .addTo(myMap);

    var markerBounds = L.latLngBounds(startMarker.getLatLng(), finalMarker.getLatLng());
    myMap.flyToBounds(markerBounds);

    sendOsrmRequest(startPosition[0], startPosition[1], finalPosition[0], finalPosition[1]);
    return false;
  }
});
html,
body {
  padding: 0;
  margin: 0;
}

#myMap {
  position: absolute;
  top: 4em;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: 1;
}

#myWidget {
  position: absolute;
  z-index: 2;
}
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet.min.css">
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/themes/redmond/jquery-ui.min.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet@1/dist/leaflet-src.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-ui@1/dist/jquery-ui.min.js"></script>

<div class="ui-widget ui-front" id="myWidget">
  <label>Enter destination: <input id="myInput"></label>

  <div id="myHint">Type in at least 5 letters!</div>
</div>

<div id="myMap"></div>

为了让我的演示代码简短,我已经将起始位置硬编码为我的家乡城市。
您可以添加第二个jQuery UI自动完成输入字段来改进它。
建议的解决方案不需要任何API密钥或付款,这里的示例代码许可证是:公共领域。
如果您计划在生产中运行它,您应该安装自己的osrm-backend和Nominatim实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接