使折线捕捉到传单中的道路

Posted

技术标签:

【中文标题】使折线捕捉到传单中的道路【英文标题】:Making polyline snap to roads in leaflet 【发布时间】:2016-04-05 09:01:14 【问题描述】:

我正在从数据库中加载标记,然后在标记之间绘制一条折线。我正在使用折线来计算总距离,而不必计算从标记-a 到标记-b 到标记-c 的距离等等。

然而,我的距离并不准确,因为如果两个标记在弯曲的道路周围,多段线只是将它们连接起来,而不是沿着道路绘制。

我知道这在 Google Maps API 中是可能的,但使用限制不适合我,这就是我决定使用传单的原因。

我的标记相距不远,因为我的 GPS 设备每 10 秒发送一次位置。

我找到了leaflet-routing-machine 插件,我想知道是否可以使用它来使我的折线与道路对齐?

这就是我向地图添加标记的方式:

function getlocationsfromdb()
      group.clearLayers();
      latlngArray.length=0;
      var deviceid = $("#selectid").val();

        $.ajax(
            type: "POST",
            url: "functionhandlers/getlocations.php",
            data: deviceid:deviceid,start:start,end:end,
            dataType: 'json',
            cache: false,
        )
        .success(function(response)    
            $('input').removeClass('error').next('.errormessage').html('');
            if(!response.errors && response.result) 

                $.each(response.result, function( index, value) 
                    var latlng = L.latLng(value[7], value[8]);
                    var marker = L.circleMarker(latlng,radius:2).addTo(group);    
                    latlngArray.push(latlng);   

               );
                  var polyline = L.polyline(latlngArray, color: '#605ca8').addTo(group);  
                  map.fitBounds(group.getBounds());
                  var distancetravelled=polyline.measuredDistance();
                  $("#distancetravelled").html(distancetravelled);


             else 
                $.each(response.errors, function( index, value) 
                    // add error classes
                    $('input[name*='+index+']').addClass('error').after('<div class="errormessage">'+value+'</div>')
                );
            
        ); 

有人可以指点我正确的方向吗?

【问题讨论】:

【参考方案1】:

这可以通过传单路由机轻松完成。您可以在初始化路由控制时将waypoints 设置为您的latlngArray

var control = L.Routing.control(
  waypoints: latlngArray,
  show: false,
  waypointMode: 'snap',
  createMarker: function() 
).addTo(map);

这里,show: false 阻止控件显示在地图上,而空的 createMarker 函数会覆盖路由机器创建的默认标记,而不是什么都不做(尽管当我们移除控件时标记会被移除,这只是防止它们在找到路线时在屏幕上闪烁)。

您可以通过侦听routeselected 事件来提取路由机器结果的所有顶点,该事件将返回一个IRoute object,其中包含路线的所有方向和几何形状。将.route.coordinates 放在一个新的L.polyline 对象中将保留路由,因此我们可以摆脱路由控制:

control.on('routeselected', function(e) 
  L.polyline(e.route.coordinates).addTo(group);
  map.removeControl(control);
);

在您填充latlngArray 后立即将上述代码块放在您的.success 回调函数中应该会给您想要的路线。这是一个在工作中展示这个的小提琴:

http://fiddle.jshell.net/nathansnider/ygktexbj/

另外,如果您没有将路由控件用于其他任何事情,并且不想让它完全显示(在计算路由时可能仍会出现一个小的白色控件框),您可以简单地将其隐藏在 CSS :

.leaflet-routing-container 
  display:none;

【讨论】:

我意识到这个解决方案有点迂回,因为它创建了一个控件,然后一半的代码只是阻止该控件显示在地图上。虽然我怀疑有一种方法可以在不创建控件的情况下执行此操作,可能直接使用L.Routing.osrm,但我无法从文档中完全弄清楚。 这太棒了!感谢您花时间向我详细解释,非常感谢 Nathan! :) 小提琴已经死了:(【参考方案2】:

我意识到这个解决方案有点迂回,因为它创建了一个控件,然后一半的代码只是阻止该控件显示在地图上

您实际上不必将其添加到地图中。此外,您可以直接攻击内部路由器的route函数。

var routingControl = L.Routing.control(
  waypointMode: 'snap'
);

然后

routingControl._router.route(latLngCoordinates, function(err, waypoints) 
  var a = waypoints;
);

小心,这是原始复制/粘贴: - 航点适合内部格式(检查它) - latLngCoordinates 必须是 lat:, lng: 格式 - 它可能需要一些清理,因为生成的 url 封装了一些很长的“提示”数据。

【讨论】:

以上是关于使折线捕捉到传单中的道路的主要内容,如果未能解决你的问题,请参考以下文章

绘制折线捕捉到道路Android谷歌地图应用程序

如何制作混合路径道路类型? (捕捉到道路和简单的折线)Google Maps API

折线与Bing地图中的道路对齐

如何在传单中的两个标记之间添加路线(折线)

旋转传单折线/矩形

如何在 Android Studio 中添加捕捉到道路谷歌地图