如何计算给定点到最近道路的距离?

Posted

技术标签:

【中文标题】如何计算给定点到最近道路的距离?【英文标题】:How to calculate distance of a given point to the nearest road? 【发布时间】:2014-06-16 14:31:35 【问题描述】:

目标:

计算给定点到最近道路的距离。 我需要确定一个点是否落在道路上。为此,我想查看从该点到最近道路的距离。因此,距离为 0 意味着该点实际上位于道路上。

其他信息:

我不受限于谷歌地图。如果 Bing 地图或其他地图服务提供此功能,那么该服务也值得考虑。

问题:

您知道使用 Google Maps API v3 计算从给定点到最近道路的距离的方法吗?如果不是,您是否知道我可以实现目标的另一种方法或服务?

【问题讨论】:

Google maps api - snap marker to nearest road 的可能重复项 【参考方案1】:

问题解决了。这是演示:http://jsfiddle.net/63sWv/

var marker = null;
var roadMarker = null;
var geocoder = new google.maps.Geocoder();
var map;
var directionsService = new google.maps.DirectionsService();

$(document).ready(function()

    var latlng = new google.maps.LatLng(54.97430382488778, -1.611546277999878);

    var mapOptions = 
        zoom: 22,
        center: latlng
    ;

    map = new google.maps.Map(document.getElementById('map'), mapOptions);

    google.maps.event.addListener(map, 'click', function(event)        
        placeMarkers(event);
    );

);

function placeMarkers(e) 

    var markerImage = "https://chart.googleapis.com/chart?chst=d_map_pin_icon&chld=home|FFFF00";    
    var roadMarkerImage ="https://chart.googleapis.com/chart?chst=d_map_xpin_letter&chld=pin||FF0000|000000";

    if(marker !== null)
        marker.setMap(null);
    

    marker = new google.maps.Marker(
        position: e.latLng,
        map: map,
        icon: markerImage
    );

    var request = 
        origin:e.latLng, 
        destination:e.latLng,
        travelMode: google.maps.DirectionsTravelMode.DRIVING
      ;

    directionsService.route(request, function(response, status) 

        if (status == google.maps.DirectionsStatus.OK)         

            if(roadMarker !== null)
                roadMarker.setMap(null);    
            

            roadMarker = new google.maps.Marker(
                position: response.routes[0].legs[0].start_location,
                map: map,
                icon: roadMarkerImage
            );         

            var distance = getDistance(request.origin,            
                            response.routes[0].legs[0].steps[0].end_point);

            $(".output .distance").html(distance);

        
    );  


var rad = function(x) 
  return x * Math.PI / 180;
;

var getDistance = function(p1, p2) 

    //trim up to 5 decimal places because it is at that point where the difference
    p1.lat = parseFloat(p1.lat().toFixed(5));
    p1.lng = parseFloat(p1.lng().toFixed(5));

    p2.lat = parseFloat(p2.lat().toFixed(5));
    p2.lng = parseFloat(p2.lng().toFixed(5));

    var R = 6378137; // Earth’s mean radius in meter
    var dLat = rad(p2.lat - p1.lat);
    var dLong = rad(p2.lng - p1.lng);

    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(rad(p1.lat)) * Math.cos(rad(p2.lat)) * Math.sin(dLong / 2) * Math.sin(dLong / 2);

    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c;

    return d; // returns the distance in meter

;

【讨论】:

感谢您成为出色的 *** 用户之一,他们实际告诉您他们的解决方案:D 完美!正是我需要的。谢谢。【参考方案2】:

另一种可能性是使用 Google 的 Road Snap API:https://developers.google.com/maps/documentation/roads/snap

其实很简单。您提供您的位置点,它会返回最近的道路点,例如像这样: https://roads.googleapis.com/v1/snapToRoads?key=your_api_key&path=60.170880,24.942795

它返回这个:


  "snappedPoints": [
    
      "location": 
        "latitude": 60.170877918672588,
        "longitude": 24.942699821922421
      ,
      "originalIndex": 0,
      "placeId": "ChIJNX9BrM0LkkYRIM-cQg265e8"
    
  ]

【讨论】:

【参考方案3】:

我需要确定一个点是否落在道路上。


我不认为有合法的方法可以使用这些 API 做你想做的事。但是,您可能会使用 Google 的 Street View Image API 或使用 Google Maps API's StreetView objects 进行更细粒度的控制来做一些不推荐的黑客技巧。

想法如下:如果 Street View API 返回有效结果(即全景街景图像),那么您可能在街道上。如果没有,那么你不在街上。

使用stand-alone Street View Image API 识别“真实”响应可能存在挑战。一种选择是将失败响应的图像文件大小like this one(其 Content-Length 为 4868)与为测试点返回的图像文件大小(例如 a valid one like this)进行比较,后者具有 Content-长度为 38701 ..任何“真”响应都会导致图像具有明显更高的 Content-Length 值,因为图像中有实际数据。坦率地说,只要您请求相同大小的图像(即宽度和高度),失败的 Content-Length 应该始终相同。然而,API 可能会发生细微的变化并打破这种期望。所以这是有风险的。

实际Google Maps javascript API's Street View objects 提供的更高粒度的控制将为您提供更清晰的处理,因为google.maps.StreetViewStatus 将返回三个值之一并解决此条件:OKUNKNOWN_ERRORZERO_RESULTS,如果您使用之前描述的静态图像 API,则无需进行脆弱的猜测工作。

但是这种方法很脏。首先,我认为街景不仅仅是近街图像。我正在考虑公园中的小径、用户上传的全景图等。其次,Street View API 似乎使用了松散的“捕捉”容差 (like, 50 meters)。换句话说,如果你的观点足够接近,它会给你带来怀疑的好处,并且无论如何都会返回附近的街景全景图。换句话说,要小心误报。

如果您正在考虑采用这种方法,以下是一个有效的端点示例:

http://maps.googleapis.com/maps/api/streetview?size=600x300&location=34.055526,-81.008087

这是一个失败的..

http://maps.googleapis.com/maps/api/streetview?size=600x300&location=34.05637,-81.00583

作为后记,如果您的应用程序的需求是由铁定的业务需求定义的,我不建议您实际使用这种方法。但如果只是为了好玩和游戏,或许就够近了吧?

如果您想认真对待这一点,您确实需要了解 PostGRESql 及其 PostGIS 扩展,并且您需要一组超级详细的街道中心线。 Open Street Map data 可以帮助您入门,但请注意,该数据的质量是可变的 ..在某些地方令人惊讶 ..比其他地方少。

【讨论】:

感谢您的建议。我以前尝试过街景方法,但认为它不实用。许多街道没有被覆盖,有些在房屋内,并且它们不是连续的溪流 - 似乎有街景位置的“点”,而不是整条路径。我现在正在尝试使用标记捕捉到最近的道路的谷歌方向服务 - 想法是起点和目的地之间的巨大差异等同于不在路上......但是,这被证明是棘手的,因为我不确定哪个坐标找出差异。【参考方案4】:

如果它是一条直线,您可以选择直线的中点并获得到该点的欧几里得距离:http://en.m.wikipedia.org/wiki/Euclidean_distance。

【讨论】:

以上是关于如何计算给定点到最近道路的距离?的主要内容,如果未能解决你的问题,请参考以下文章

sklearn:从点到最近的集群获取距离

如何计算给定标题上最近的国家?

给定纬度和经度的最近道路

如何使用带有 R 的 OSM 计算从某个点到 POI 的距离

如何计算 PostGIS 中离线串最近的点?

python 找到一条点到一条线上最近点的距离