代码之家  ›  专栏  ›  技术社区  ›  NullPointerException

Google地图:如何在每个PolylineOptions矩形的中间绘制箭头?

  •  0
  • NullPointerException  · 技术社区  · 7 年前

    我正在显示一条路线 PolylineOptions 从一个点到下一个点绘制矩形。

    在每个点我都画一个圆。

    目标是在每一个中间画一个箭头 直接的。这个箭头将代表路线的方向。问题是我找不到怎么做。

    这是我的代码:

        PolylineOptions rectOptions = new PolylineOptions();
        float[] prevHSV = new float[3];
        Color.colorToHSV(getResources().getColor(R.color.colorPrimary), prevHSV);
        rectOptions.color(Color.HSVToColor(255, prevHSV));
    
        String[][] routeInformation = ((MyApplication)getApplication()).getLineInformation(line);
        ArrayList<Double[]> routeStops = Util.getFullRouteFromLine(this, line);
        final LatLngBounds.Builder builder = new LatLngBounds.Builder();
    
        for (int i=0; i<routeInformation.length; i++){
            LatLng latlng = new LatLng(Double.parseDouble(routeInformation[i][0]),Double.parseDouble(routeInformation[i][1]));
            builder.include(latlng);
            mMap.addCircle(new CircleOptions().center(latlng).radius(15).strokeColor(Color.HSVToColor(255, prevHSV)).fillColor(Color.HSVToColor(255, prevHSV)).zIndex(7777));            
        }
    
        for (Double[] pos : routeStops){
            rectOptions.add(new LatLng(pos[0],pos[1])).width(5);
        }
        mMap.addPolyline(rectOptions);
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Andrii Omelchenko    7 年前

    最简单的方法是使用北向的标记(重要的是标记的旋转角度从北开始)箭头(如下所示 marker )-将其放置在当前多段线线段的中间, rotate 它按照方向设定它的属性 anchor() 属性到 (0.5,0.5) flat 到 true 。像这样的:

     ...
     // place first point of route (direction can't be calculated for it)
     LatLng prevLatLng = new LatLng(Double.parseDouble(routeInformation[0][0]),Double.parseDouble(routeInformation[0][1]));
     builder.include(prevLatLng);
     mMap.addCircle(new CircleOptions().center(prevLatLng).radius(15).strokeColor(Color.HSVToColor(255, prevHSV)).fillColor(Color.HSVToColor(255, prevHSV)).zIndex(7777));       
    
     // place other points
     for (int i=1; i<routeInformation.length; i++){
        LatLng latlng = new LatLng(Double.parseDouble(routeInformation[i][0]),Double.parseDouble(routeInformation[i][1]));
        builder.include(latlng);
        mMap.addCircle(new CircleOptions().center(latlng).radius(15).strokeColor(Color.HSVToColor(255, prevHSV)).fillColor(Color.HSVToColor(255, prevHSV)).zIndex(7777));
    
        // determine middle of segment
        LatLng middleLatLng = getMiddlePoint(prevLatLng, latlng);
    
        // determine direction
        float direction = bearingBetweenLocations(prevLatLng, latlng);
    
        // add marker with arrow      
        mMap.addMarker(new MarkerOptions()
        .position(middleLatLng)
        .anchor(0.5,0.5)
        .rotation(direction)
        .flat(true));       
    
        // move previous position to current
        prevLatLng = latlng;
    }
    ...
    

    private LatLng getMiddlePoint(LatLng latlng1, LatLng latlng2) {
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        builder.include(latlng1);
        builder.include(latlng2);  
        LatLngBounds bounds = builder.build();
        return bounds.getCenter();
    }
    

    或与 SphericalUtil.interpolate(LatLng from, LatLng to, double fraction) 从 Google Maps Android API Utility Library

    LatLng middleLatLng = SphericalUtil.interpolate(prevLatLng, latlng, 0.5);
    

    方向可以在两个相邻的路线点上确定,如 this satti8893 :

    private double bearingBetweenLocations(LatLng latLng1,LatLng latLng2) {
    
        double PI = 3.14159;
        double lat1 = latLng1.latitude * PI / 180;
        double long1 = latLng1.longitude * PI / 180;
        double lat2 = latLng2.latitude * PI / 180;
        double long2 = latLng2.longitude * PI / 180;
    
        double dLon = (long2 - long1);
    
        double y = Math.sin(dLon) * Math.cos(lat2);
        double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
                * Math.cos(lat2) * Math.cos(dLon);
    
        double brng = Math.atan2(y, x);
    
        brng = Math.toDegrees(brng);
        brng = (brng + 360) % 360;
    
        return brng;
    }
    

    注意!这不是完整的代码,只是一个想法。

    this 问题 Scorpion

    另一种方法是创建基于MapView的自定义视图,并在覆盖中手动绘制带有线、圆和箭头的整个路径 dispatchDraw() .