1

path()jsonオブジェクトから作成されたを持っています。JSONオブジェクトをコンストラクターのオーバーレイオブジェクトに渡します。

拡張するオブジェクトは、マップを移動、レンダリング、タッチするなど、Overlayいつでも呼び出すことができます。draw()オーバーレイが表示されていない、近くにない、または何もない場合でも。

jsonオブジェクトにはネストされたjson配列が含まれているため、実際にはネストされたループであるforループでパスオブジェクトを生成したいと思います。draw()これは理論上の計算時間が長いので、メソッドで実行したくありません。代わりに、コンストラクターでロジックを実行してファイルを作成し、ここで必要なメソッドでpath()そのパスファイルを1回だけ呼び出すようにしました。draw()canvas.drawPath(path, mPaint);

残念ながら、コンストラクターでパスを作成すると、マップと一緒にパンしません。しかし、私がそれを作成するとき、まったく同じコードで、draw()メソッドで、それは望ましい機能を持っています:地図の一部を囲うパス。

問題は、draw()メソッドが私のdouble forループを何度も呼び出すことであり、パフォーマンスへの影響は明らかであり、衰弱させます。draw()内にループを入れても、new Thread()パフォーマンスは向上しません。コンストラクターで実行するのが理想的ですが、パスはマップと一緒にパンしません。

同様に、メソッド内にプライベートブールフリップを配置draw()して、目的のコードのみを実行することも機能しません。パスが絶えず再描画されていない限り、パスはマップに表示されません。これは、作業が非常に困難です。

この問題に関するこのサイトの他の回答の問題は、人々が正方形、円、画像draw()を作成していることです。これらは、パスを生成するためのループではなく、内で1回の呼び出しのみを必要とします。

提案?メソッドに関する何かdraw()がオーバーレイをマップに貼り付けるのに役立ちます。forループを1回だけ実行するにはどうすればよいですか。

4

2 に答える 2

2

あなたのためのいくつかの考慮事項:

  1. draw()メソッドをオーバーライドしないでください。オーバーレイクラスは、すでにパン操作全体を処理します。あなたがそれを見つけるドキュメントを読んでください。

  2. 新しいAPIは数千倍使いやすくなっています。次のような単純なコードを使用します。

    PolylineOptions p = new new PolylineOptions().width(3).color(0xFFEE8888);
    for( //... first for .... ){
       for( // .... how many you'll need to nest... ){
          // compute your JSON and get lat/long pair
          p.add(new LatLng(lat, lon));
        }
     }
     getMap().addPolyline(p);
    

マップクラスにパンとズームを処理させます。

于 2012-12-18T17:48:06.123 に答える
0

あなたはすでに答えを受け入れていますが、ここに私がこれに使用するアプローチがあります。以下のサンプルコードでは、古いものを使用してMapViewいますが、この概念はどのバージョンでも機能するはずです。私もmapforges(最小限の調整で)それを使用しています。

コンセプト

  • path最初の呼び出しであなたを構築しdraw()、point(0)の位置を記録します
  • 次にdraw()、point(0)の位置が変更された場合、マップは移動しました。描画する前に、「パス」を同じ値でオフセットします。
  • ズームが変更された場合は、pathオブジェクトを再作成します。

パフォーマンス

中距離デバイスに10.000ポイントのパスがある場合、2 msキャッシュされたdraw()呼び出しごとに約かかります。パスを再構築する必要がある場合(ズームを変更した場合)、約80 ms

もちろん、さまざまなパスズームレベルをキャッシュして、メモリを増やすことでパフォーマンスを少し向上させることもできます。

サンプルコード

draw()メソッドは、ズームの変更があるかどうか(ある場合はパスを再構築するように依頼する)、およびマップが移動したかどうか(ある場合はオフセットパス)のみをチェックし、最後にパスを描画します。

@Override
public void draw(Canvas canvas, MapView mapview, boolean shadow) {
    super.draw(canvas, mapview, shadow);
    if(shadow) return;
    if(mp.getPoints() == null || mp.getPoints().size() < 2) return;

    Projection projection = mapview.getProjection();
    int lonSpanNew = projection.fromPixels(0,mapview.getHeight()/2).getLongitudeE6() - 
            projection.fromPixels(mapview.getWidth(),mapview.getHeight()/2).getLongitudeE6();
    if(lonSpanNew != pathInitialLonSpan)
        pathBuild();
    else{ //check if path need to be offset
        projection.toPixels(mp.getPoints().get(0), p1);
        if(p1.x != pathInitialPoint.x || p1.y != pathInitialPoint.y){
            path.offset(p1.x - pathInitialPoint.x, p1.y - pathInitialPoint.y);
            pathInitialPoint.x = p1.x;
            pathInitialPoint.y = p1.y;
        }

    }
    canvas.drawPath(path, paint); 
}

ズームが変更されるたびにパスを作成する必要があります。getZoomLevel()はマップズームアニメーションと同期していないため、ズーム変更の検出はpathInitialLonSpanを使用して行われます。

private void pathBuild(){
    path.rewind(); 
    if(mp.getPoints() == null || mp.getPoints().size() < 2) return;

    Projection projection = mapView.getProjection();
    pathInitialLonSpan = projection.fromPixels(0,mapView.getHeight()/2).getLongitudeE6() - 
            projection.fromPixels(mapView.getWidth(),mapView.getHeight()/2).getLongitudeE6();

    projection.toPixels(mp.getPoints().get(0), pathInitialPoint);
    path.moveTo(pathInitialPoint.x,pathInitialPoint.y); 

    for(int i=1; i<mp.getPoints().size(); i++){
        projection.toPixels(mp.getPoints().get(i), p1);
        int distance2 = (pPrev.x - p1.x) * (pPrev.x - p1.x) + (pPrev.y - p1.y) * (pPrev.y - p1.y); 
        if(distance2 > 9){
            path.lineTo(p1.x,p1.y);
            pPrev.set(p1.x, p1.y);
        }
    }

よろしく。

于 2012-12-23T11:30:02.410 に答える