5

)巨大な(100k +)GeoPointセットからAndroidのMapViewへのパスを描画する際に問題を解決しようとしています。 まず、私はStackOverflowを多く検索し、答えを見つけられませんでした。私のコードのボトルネックは実際にキャンバスに描画されていませんが、Projection.toPixels(GeoPoint, Point)またはRect.contains(point.x, point.y)メソッドです。現在のズームレベルに応じてn番目の点だけを表示します。地図がズームインされているときは、できるだけ正確なパスを表示したいので、ゼロ点(またはゼロに近い点)をスキップして、可視点を見つけるときにコレクション内のすべての点についてプロジェクションメソッドを呼び出す必要があります。そして、それは本当に多くの時間がかかります(秒ではありませんが、地図のパニングは流動的ではなく、HTC Wildfireでテストしていません:))。計算されたポイントをキャッシングしようとしましたが、マップのパン/ズーム後にポイントが再計算されるため、 はまったく役に立ちませんでした。AndroidのMapViewに100k +ポイントを描画する(

配列を繰り返し処理するのではなく、何らかのプルーンと検索アルゴリズムの使用について考えましたが、入力データがソートされていないことがわかりました(2つの目に見えない点の間に何点も捨てることはできません)。それは私が最初に簡単なソートで解決することができますが、私はまだ対数の数字でもgetProjection()Rect.contains(point.x, point.y)の呼び出しは、パフォーマンスの問題を解決するリニアのではないと確信しています。

ベローが私の現在のコードです。あなたがこれをより良くする方法を知っているなら、私を助けてください。どうもありがとう!

public void drawPath(MapView mv, Canvas canvas) { 
    displayed = false; 

    tmpPath.reset(); 

    int zoomLevel = mapView.getZoomLevel(); 
    int skippedPoints = (int) Math.pow(2, (Math.max((19 - zoomLevel), 0))); 
    int mPointsSize = mPoints.size(); 
    int mPointsLastIndex = mPointsSize - 1; 
    int stop = mPointsLastIndex - skippedPoints; 

    mapView.getDrawingRect(currentMapBoundsRect); 
    Projection projection = mv.getProjection(); 

    for (int i = 0; i < mPointsSize; i += skippedPoints) { 

     if (i > stop) { 
      break; 
     } 
//HERE IS THE PROBLEM I THINK - THIS METHOD AND THE IF CONDITION BELOW 
     projection.toPixels(mPoints.get(i), point); 

     if (currentMapBoundsRect.contains(point.x, point.y)) { 
      if (!displayed) { 
       Point tmpPoint = new Point(); 
       projection.toPixels(mPoints.get(Math.max(i - 1, 0)), 
         tmpPoint); 
       tmpPath.moveTo(tmpPoint.x, tmpPoint.y); 
       tmpPath.lineTo(point.x, point.y); 
       displayed = true; 
      } else { 

       tmpPath.lineTo(point.x, point.y); 

      } 

     } else if (displayed) { 
      tmpPath.lineTo(point.x, point.y); 
      displayed = false; 

     } 

    } 

    canvas.drawPath(tmpPath, this.pathPaint); 

} 
+0

私はいくつかのトレースを行いました。約85%の負荷は 'Projection.toPixels()'メソッドを取ります。それを最適化する方法が必要です:/ – simekadam

+0

別の方法ではある種のマッピングを使用することができます。世界を矩形のセグメントに分割し、それらを現在のmapView状態に従ってフィルタリングするなど、キーをキーとするHashMap。その後、HashMapから取り出して表示します。 これはかなり複雑に見えます:)それは可能だと思いますか?それが意味をなさないかどうかだけ。 – simekadam

答えて

3

だから私はずっと速くする方法を考え出しました! 私はここに投稿します。 projection.toPixels()の使用が実際にアプリケーションのパフォーマンスを損なう可能性があることが明らかになりました。だから私はそれがマップビューポートに含まれている場合、すべての単一GeoPointを取るPointに変換してからチェックよりも優れている方法を考え出したですが、私は次のようにマップのactuallビューポートの半径を数えるとき:

mapView.getGlobalVisibleRect(currentMapBoundsRect); 
    GeoPoint point1 = projection.fromPixels(currentMapBoundsRect.centerX(), currentMapBoundsRect.centerY()); 
    GeoPoint point2 = projection.fromPixels(currentMapBoundsRect.left, currentMapBoundsRect.top); 
    float[] results2 = new float[3]; 
    Location.distanceBetween(point1.getLatitudeE6()/1E6, point1.getLongitudeE6()/1E6, point2.getLatitudeE6()/1E6, point2.getLongitudeE6()/1E6, results2); 

半径が結果2にあります。

私はすべてGeoPointを1つ取り、マップの中心との距離を数えますmapView.getMapCenter()。次に、半径を計算された距離と比較し、ポイントを表示しないかどうかを決定できます。

だから、それは役に立つと思っています。

関連する問題