8

Android Maps V2 API を使用して、矢印の付いたポリライン (方向を示します) を描画する方法。Android マップ ドキュメントでは、このオプションは利用できません。ポリラインに矢印を追加することは可能ですか?

4

3 に答える 3

13

JavaScript の例 ( http://econym.org.uk/gmap/example_arrows.htm ) を Java コードに変換することにより、Doug が提案したのと同じ概念を使用して開発した実用的な例を次に示します。便宜上、Google マップ サーバーからの画像を使用しますが、これらはあなたのデザインの画像であったり、ウェブからこすり落としてアプリにローカルに保存されたりする可能性があります。デモンストレーションのためにメインスレッドでこれらをダウンロードしていますが、ライブアプリで使用する場合はダウンロードしないでください!!

ただし、JavaScript の例との主な違いは、矢印の頭の画像を 4 倍のサイズの大きな画像に投影し、A から B への方位に基づいて画像を変換する場所を見つけ、最後にその画像を中央に配置する必要があることです。アイコンの大きな画像を使用して別のアンカー マーカーを追加することにより、既存の B マーカー。

最初にポリラインを追加します。

PolylineOptions polylines = new PolylineOptions();

LatLng from = new LatLng(f.getLatitude(), f.getLongitude());
LatLng to = new LatLng(t.getLatitude(), t.getLongitude());

polylines.add(from, to).color(polyColor).width(2);

mMap.addPolyline(polylines);

DrawArrowHead(mMap, from, to);

次に、矢頭を追加します。

private final double degreesPerRadian = 180.0 / Math.PI;

private void DrawArrowHead(GoogleMap mMap, LatLng from, LatLng to){
    // obtain the bearing between the last two points
    double bearing = GetBearing(from, to);

    // round it to a multiple of 3 and cast out 120s
    double adjBearing = Math.round(bearing / 3) * 3;
    while (adjBearing >= 120) {
        adjBearing -= 120;
    }

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy); 

    // Get the corresponding triangle marker from Google        
    URL url;
    Bitmap image = null;

    try {
        url = new URL("http://www.google.com/intl/en_ALL/mapfiles/dir_" + String.valueOf((int)adjBearing) + ".png");
        try {
            image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    if (image != null){

        // Anchor is ratio in range [0..1] so value of 0.5 on x and y will center the marker image on the lat/long
        float anchorX = 0.5f;
        float anchorY = 0.5f;

        int offsetX = 0;
        int offsetY = 0;

        // images are 24px x 24px
        // so transformed image will be 48px x 48px

        //315 range -- 22.5 either side of 315
        if (bearing >= 292.5 && bearing < 335.5){
            offsetX = 24;
            offsetY = 24;
        }
        //270 range
        else if (bearing >= 247.5 && bearing < 292.5){
            offsetX = 24;
            offsetY = 12;
        }
        //225 range
        else if (bearing >= 202.5 && bearing < 247.5){
            offsetX = 24;
            offsetY = 0;
        }
        //180 range
        else if (bearing >= 157.5 && bearing < 202.5){
            offsetX = 12;
            offsetY = 0;
        }
        //135 range
        else if (bearing >= 112.5 && bearing < 157.5){
            offsetX = 0;
            offsetY = 0;
        }
        //90 range
        else if (bearing >= 67.5 && bearing < 112.5){
            offsetX = 0;
            offsetY = 12;
        }
        //45 range
        else if (bearing >= 22.5 && bearing < 67.5){
            offsetX = 0;
            offsetY = 24;
        }
        //0 range - 335.5 - 22.5
        else {
            offsetX = 12;
            offsetY = 24;
        }

        Bitmap wideBmp;
        Canvas wideBmpCanvas;
        Rect src, dest;

        // Create larger bitmap 4 times the size of arrow head image
        wideBmp = Bitmap.createBitmap(image.getWidth() * 2, image.getHeight() * 2, image.getConfig());

        wideBmpCanvas = new Canvas(wideBmp); 

        src = new Rect(0, 0, image.getWidth(), image.getHeight());
        dest = new Rect(src); 
        dest.offset(offsetX, offsetY); 

        wideBmpCanvas.drawBitmap(image, src, dest, null);

        mMap.addMarker(new MarkerOptions()
        .position(to)
        .icon(BitmapDescriptorFactory.fromBitmap(wideBmp))
        .anchor(anchorX, anchorY));
    }
}

private double GetBearing(LatLng from, LatLng to){
    double lat1 = from.latitude * Math.PI / 180.0;
    double lon1 = from.longitude * Math.PI / 180.0;
    double lat2 = to.latitude * Math.PI / 180.0;
    double lon2 = to.longitude * Math.PI / 180.0;

    // Compute the angle.
    double angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );

    if (angle < 0.0)
        angle += Math.PI * 2.0;

    // And convert result to degrees.
    angle = angle * degreesPerRadian;

    return angle;
}
于 2013-08-15T11:27:41.937 に答える