简体   繁体   English

我可以在Google Maps Android中绘制弯曲的虚线吗?

[英]Can I draw a curved dashed line in Google Maps Android?

In Google Maps from browser which has the curved dashed line look like this: 在具有弯曲虚线的浏览器的Google地图中,如下所示: 在此输入图像描述

But when I implement Google Maps in my own Android project, it didn't show this line 但是,当我在自己的Android项目中实施Google地图时,它并未显示此行

在此输入图像描述

How can I draw this line? 我怎么画这条线?

You can implement the curved dashed polyline between two points. 您可以在两点之间实现弯曲的虚线折线。 For this purpose you can use Google Maps Android API Utility Library that has SphericalUtil class and apply some math in your code to create a polyline. 为此,您可以使用具有SphericalUtil类的Google Maps Android API实用程序库 ,并在代码中应用一些数学运算来创建折线。

You have to include the utility library in your gradle as 您必须将实用程序库包含在gradle中

compile 'com.google.maps.android:android-maps-utils:0.5' . compile 'com.google.maps.android:android-maps-utils:0.5'

Please have a look at my sample Activity and function showCurvedPolyline (LatLng p1, LatLng p2, double k) that constructs dashed curved polyline between two points. 请查看我的示例活动和函数showCurvedPolyline (LatLng p1, LatLng p2, double k) ,它构造两点之间的虚线弯曲折线。 The last parameter k defines curvature of the polyline, it can be >0 and <=1. 最后一个参数k定义折线的曲率,它可以> 0且<= 1。 In my example I used k=0.5 在我的例子中,我使用k = 0.5

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

private GoogleMap mMap;
private LatLng sydney1;
private LatLng sydney2;

@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;

    mMap.getUiSettings().setZoomControlsEnabled(true);

    // Add a marker in Sydney and move the camera
    sydney1 = new LatLng(-33.904438,151.249852);
    sydney2 = new LatLng(-33.905823,151.252422);

    mMap.addMarker(new MarkerOptions().position(sydney1)
            .draggable(false).visible(true).title("Marker in Sydney 1"));
    mMap.addMarker(new MarkerOptions().position(sydney2)
            .draggable(false).visible(true).title("Marker in Sydney 2"));

    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney1, 16F));

    this.showCurvedPolyline(sydney1,sydney2, 0.5);
}

private void showCurvedPolyline (LatLng p1, LatLng p2, double k) {
    //Calculate distance and heading between two points
    double d = SphericalUtil.computeDistanceBetween(p1,p2);
    double h = SphericalUtil.computeHeading(p1, p2);

    //Midpoint position
    LatLng p = SphericalUtil.computeOffset(p1, d*0.5, h);

    //Apply some mathematics to calculate position of the circle center
    double x = (1-k*k)*d*0.5/(2*k);
    double r = (1+k*k)*d*0.5/(2*k);

    LatLng c = SphericalUtil.computeOffset(p, x, h + 90.0);

    //Polyline options
    PolylineOptions options = new PolylineOptions();
    List<PatternItem> pattern = Arrays.<PatternItem>asList(new Dash(30), new Gap(20));

    //Calculate heading between circle center and two points
    double h1 = SphericalUtil.computeHeading(c, p1);
    double h2 = SphericalUtil.computeHeading(c, p2);

    //Calculate positions of points on circle border and add them to polyline options
    int numpoints = 100;
    double step = (h2 -h1) / numpoints;

    for (int i=0; i < numpoints; i++) {
        LatLng pi = SphericalUtil.computeOffset(c, r, h1 + i * step);
        options.add(pi);
    }

    //Draw polyline
    mMap.addPolyline(options.width(10).color(Color.MAGENTA).geodesic(false).pattern(pattern));
}

}

You can download a sample project with complete code from GitHub 您可以从GitHub下载包含完整代码的示例项目

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

Just replace my API key with yours in the app/src/debug/res/values/google_maps_api.xml 只需在app/src/debug/res/values/google_maps_api.xml您的API密钥替换为您的API密钥

在此输入图像描述

Thanks @xomena for the solution above. 感谢@xomena上面的解决方案。 It works beautifully in most cases. 它在大多数情况下都很漂亮。 But there needs some improvement: 但是需要一些改进:

  • When k == 1 , x will be 0 and midpoint (p) will be the same as mid curve point (c). k == 1 ,x将为0,中点(p)将与中间曲线点(c)相同。 That means it should be a straight line, but then when you calculate the step, it's not Zero so the final result is a half-circle curve, which is ambiguous with the above condition. 这意味着它应该是一条直线,但是当你计算步数时,它不是零,所以最终结果是半圆曲线,这与上述条件不一致。

  • When the curve is long enough, let say LIMIT = 1000km , each calculation in h1 + i * step inside the loop make a tiny error to the correct value (due to java double calculation error I guess). 当曲线足够长时,假设LIMIT = 1000km ,循环内的h1 + i * step每个计算都会产生一个小错误到正确的值(由于java double计算错误,我猜)。 Then the start and end points of the polyline not exactly match with start and end coordinations. 然后折线的起点和终点与开始和结束协调不完全匹配。 Moreover, the curvature of the polyline is unpredictable, base on my research, the reason can be the curvature of the Earth's surface that can make your calculation base on heading not correct. 此外,根据我的研究,折线的曲率是不可预测的,原因可能是地球表面的曲率,这可能使你的计算基于航向不正确。

My quick fix is to reset the step to 0 if k == 1 to make it a straight line. 我的快速解决方法是, if k == 1 ,将step重置为0,使其成为一条直线。 For the second problem, if the distance between 2 points is greater than a LIMIT of 1000km, drawing a straight line with k = 1 will be a safer choice to me. 对于第二个问题,如果2点之间的距离大于1000km的LIMIT,绘制一条k = 1的直线对我来说将是一个更安全的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM