如何在两条点之间沿现有道路绘制路线? [英] How do I draw a route, along an existing road, between two points?

查看:64
本文介绍了如何在两条点之间沿现有道路绘制路线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的android应用中显示两个位置之间的行驶路线.我只想在路段的顶部绘制路线.

I want to show the driving route between two locations in my android app. I want to draw the route only on top of road segments.

关于堆栈溢出本身有几个答案,并且所有答案都使用相同的方法.使用Google Directions API获取从起点到目的地的路线,并在返回的点之间绘制一条折线.以下是使用此方法的一些答案.

There are several answers on stack overflow itself, and all of them were using the same method. Get the directions from start point to destination using google directions API, and draw a polyline across the points returned. Following are some of the answers which uses this method.

https://stackoverflow.com/a/17007360/1015678

https://stackoverflow.com/a/40563930/1015678

但是,上述方法的问题是,当道路不平直时,黎明的死记号并不总是位于道路的顶部,因为Directions API仅返回您需要从一条道路转为另一条道路(在交叉路口)的点.它不会在同一路段的转弯处给出点详细信息.因此,当我在道路弯道多的区域中使用上述方法时,绘制的路线几乎始终不在路段的顶部.

But, problem with above method is, when the roads are not straight, the dawn rote is not always on top of the roads, because directions API only returns points where you need to turn from one road to another (at junctions). It doesn't give point details in the bends of the same road segment. So, when I use above method in an area where the roads have so many bends, the route drawn almost always is not on top of road segments.

我找到了答案,该答案正是我使用JavaScript API所要做的.在此解决方案中,绘制的路线很好地沿着道路行驶,类似于google maps android应用.有人知道这在Android应用程序中是否可以实现?

I found this answer, which does what I need to do, using the javascript API. In this solution, the drawn route nicely follows the roads, similar to the google maps android app. Does someone know whether this is achievable in an android app?

Google Maps android应用可以很好地绘制从一个点到另一个点的路线,使路线保持在道路上.有人知道Google Maps是如何做到的吗?是否使用未公开的其他任何API?

Google Maps android app can nicely draw a route from one point to another, keeping the route on the roads. Does anyone know how Google Maps is doing this? Is it using any other API which is not publicly exposed?

推荐答案

实际上,您可以使用Directions API网络服务提供的结果在Google Maps Android API中绘制精确的路线.如果您阅读了 Directions API 的文档,您将看到响应包含信息关于路线的腿和脚步.每个步骤都有一个字段polyline,在文档中将其描述为

Indeed, you can draw precise route in Google Maps Android API using results provided by Directions API web service. If you read the documentation for Directions API you will see that response contains information about route legs and steps. Each step has a field polyline that is described in the documentation as

折线包含一个单点对象,该对象包含步骤的编码折线表示.该折线是该步骤的近似(平滑)路径.

polyline contains a single points object that holds an encoded polyline representation of the step. This polyline is an approximate (smoothed) path of the step.

因此,解决您问题的主要思路是从Directions API获得响应,遍历路线分支和步骤,每一步都获得

So, the main idea to solve your issue is to get response from Directions API, loop through route legs and steps, for each step get encoded polyline and decode it to the list of coordinates. Once done you will have a list of all coordinates that compound the route, not only begin and end point of each step.

为简单起见,我建议将Java客户端库用于Google Maps Web服务:

For simplicity I recommend using the Java client library for Google Maps Web services:

https://github.com/googlemaps/google-maps-services-java

使用此库,您可以避免实现自己的异步任务和多段线的解码功能.阅读文档以了解如何在项目中添加客户端库.

Using this library you can avoid implementing your own async tasks and decoding function for polylines. Read the documentation to figure out how to add the client library in your project.

在Gradle中,它应该类似于

In Gradle it should be something similar to

compile 'com.google.maps:google-maps-services:(insert latest version)'
compile 'org.slf4j:slf4j-nop:1.7.25'

我创建了一个简单的示例来演示其工作原理.看看我在代码中的注释

I have created a simple example to demonstrate how it works. Have a look at my comments in the code

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    private String TAG = "so47492459";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        LatLng barcelona = new LatLng(41.385064,2.173403);
        mMap.addMarker(new MarkerOptions().position(barcelona).title("Marker in Barcelona"));

        LatLng madrid = new LatLng(40.416775,-3.70379);
        mMap.addMarker(new MarkerOptions().position(madrid).title("Marker in Madrid"));

        LatLng zaragoza = new LatLng(41.648823,-0.889085);

        //Define list to get all latlng for the route
        List<LatLng> path = new ArrayList();


        //Execute Directions API request
        GeoApiContext context = new GeoApiContext.Builder()
                .apiKey("YOUR_API_KEY")
                .build();
        DirectionsApiRequest req = DirectionsApi.getDirections(context, "41.385064,2.173403", "40.416775,-3.70379");
        try {
            DirectionsResult res = req.await();

            //Loop through legs and steps to get encoded polylines of each step
            if (res.routes != null && res.routes.length > 0) {
                DirectionsRoute route = res.routes[0];

                if (route.legs !=null) {
                    for(int i=0; i<route.legs.length; i++) {
                        DirectionsLeg leg = route.legs[i];
                        if (leg.steps != null) {
                            for (int j=0; j<leg.steps.length;j++){
                                DirectionsStep step = leg.steps[j];
                                if (step.steps != null && step.steps.length >0) {
                                    for (int k=0; k<step.steps.length;k++){
                                        DirectionsStep step1 = step.steps[k];
                                        EncodedPolyline points1 = step1.polyline;
                                        if (points1 != null) {
                                            //Decode polyline and add points to list of route coordinates
                                            List<com.google.maps.model.LatLng> coords1 = points1.decodePath();
                                            for (com.google.maps.model.LatLng coord1 : coords1) {
                                                path.add(new LatLng(coord1.lat, coord1.lng));
                                            }
                                        }
                                    }
                                } else {
                                    EncodedPolyline points = step.polyline;
                                    if (points != null) {
                                        //Decode polyline and add points to list of route coordinates
                                        List<com.google.maps.model.LatLng> coords = points.decodePath();
                                        for (com.google.maps.model.LatLng coord : coords) {
                                            path.add(new LatLng(coord.lat, coord.lng));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch(Exception ex) {
            Log.e(TAG, ex.getLocalizedMessage());
        }

        //Draw the polyline
        if (path.size() > 0) {
            PolylineOptions opts = new PolylineOptions().addAll(path).color(Color.BLUE).width(5);
            mMap.addPolyline(opts);
        }

        mMap.getUiSettings().setZoomControlsEnabled(true);

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(zaragoza, 6));
    }
}

请注意,对于Web服务,您必须创建一个单独的API密钥,受Android应用限制的API密钥不适用于Web服务.

Please note that for web service you have to create a separate API key, the API key with Android app restriction won't work with web service.

我的示例的结果显示在屏幕截图中

The result of my example is shown in screenshot

您还可以从以下位置下载完整的示例项目

You can also download a complete sample project from

https://github.com/xomena-so/so47492459

别忘了用您的API密钥代替.

Don't forget replace the API key with yours.

我希望这会有所帮助!

这篇关于如何在两条点之间沿现有道路绘制路线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆