2011-07-12 63 views
4

這是我用來繪製路線的代碼。當我有1000點時,路線嚴重減慢用戶界面。也許有人可以提供一個代碼片段或鏈接,解釋如何更有效地執行路徑繪製?我知道解決這個問題的一種方法是緩存位圖路徑,但不知道如何去做。如何使路線繪製更高效?

public class PathOverlay extends Overlay{ 

private GeoPoint startPoint; 
private GeoPoint finishPoint; 
private ArrayList<GeoPoint> pathPoints; 
private Paint paint; 
private Path path; 
private Point pathStartPoint; 
private Point pathEndPoint; 

private float dx; 
private float dy; 


public PathOverlay(GeoPoint startPoint, GeoPoint finishPoint, ArrayList<GeoPoint> pathPoints, int color){ 
    this.startPoint = startPoint; 
    this.finishPoint = finishPoint; 
    this.pathPoints = pathPoints; 
    this.paint = new Paint(); 
    this.paint.setAntiAlias(true); 
    this.paint.setDither(true); 
    this.paint.setColor(color); 
    this.paint.setAlpha(150); 
    this.paint.setStrokeWidth(4); 
    this.paint.setStyle(Paint.Style.STROKE); 
} 

@Override 
public void draw(Canvas overlayCanvas, MapView mapView, boolean shadow) { 
    if(path == null) { 
     path = getPath(mapView); 
    } else { 
     path = transformPath(mapView); 
    } 
    overlayCanvas.drawPath(path, paint); 
    super.draw(overlayCanvas, mapView, shadow); 
} 

private Path getPath(MapView mapView) { 
    Projection projection = mapView.getProjection(); 
    if(path == null) { 
     path = new Path(); 
     path.setFillType(FillType.WINDING); 
    } else { 
     path.rewind(); 
    } 
    Point point = new Point(); 
    pathStartPoint = new Point(); 
    pathEndPoint = new Point(); 

    projection.toPixels(startPoint, point); 
    projection.toPixels(startPoint, pathStartPoint); 
    path.moveTo(point.x, point.y); 
    path.addCircle(point.x, point.y, (float) 2.0, Direction.CCW); 
    if (pathPoints != null) { 
     for(int i=0;i<pathPoints.size();i++) { 
      projection.toPixels(pathPoints.get(i), point); 
      path.lineTo(point.x, point.y); 
     } 
    } 
    projection.toPixels(finishPoint, point); 
    projection.toPixels(finishPoint, pathEndPoint); 
    path.lineTo(point.x-5, point.y); 
    path.addCircle(point.x-5, point.y, (float) 2.0, Direction.CCW); 


    return path; 
} 

private Path transformPath(MapView mapView) { 
    Projection projection = mapView.getProjection(); 

    Point sPoint = new Point(); 
    Point ePoint = new Point(); 
    projection.toPixels(startPoint, sPoint); 
    projection.toPixels(finishPoint, ePoint); 

    float sx = ((float)ePoint.x - (float)sPoint.x)/((float)pathEndPoint.x - (float)pathStartPoint.x); 
    float sy = ((float)ePoint.y - (float)sPoint.y)/((float)pathEndPoint.y - (float)pathStartPoint.y); 

    if(sx != 1.0 && sy != 1.0) { 
     Log.i("PathOverlay", "resized"); 
     return getPath(mapView); 
    } else { 
     Log.i("PathOverlay", "moved"); 
     Matrix matrix = new Matrix(); 

     dx = (float)sPoint.x - (float)pathStartPoint.x; 
     dy = (float)sPoint.y - (float)pathStartPoint.y; 

     matrix.postTranslate(dx, dy); 
     pathStartPoint = sPoint; 
     pathEndPoint = ePoint; 
     path.transform(matrix); 

     return path; 
    } 
} 

} 
+0

可能重複[Android在大量的經度/緯度點繪製mapView路徑](http://stackoverflow.com/questions/3387894/android-draw-a-path-on- a-mapview-from-a-large-of-longitude-latitude-points) – Pratik

回答

0

提高繪圖速度的最佳方法是減少路徑包含的點數。也許他們是沒有必要的 - 很多人只是奠定了一個和下一個之間,因此您可以通過它們進行過濾:從以前的點(簡單的方法)

最小的方位變化,(有點困難

最小距離,雖然Location類和它的方法bearingTo()應該幫助

2

可以繪製路徑透明Bitmap對象。(無論大小,你見安裝 - 這是更大的,更好的詳細路徑尚未更高的內存消耗)

確保你創造它機智h Bitmap.config.ARGB_8888爲透明度。

一旦你做到了這一點,你就可以使用兩個矩形顯示在Overlay路徑:

  • 源矩形,以確定哪些路徑的一部分是可見的
  • 一個目標矩形以確定要在Overlay的畫布上顯示這條路徑的位置。

您將使用Canvas.drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)

應該不會太困難,你所做的最重要的計算在你的transformPath方法。

補充:

實際上,你可以做到既保持吸引到一個位圖的路徑,並重繪實際路徑的結合點。當用戶在地圖上移動或放大/縮小時使用上述技術,然後在用戶放開屏幕時重繪路徑。

+0

我想用你的方法,但是我看到了一些問題。如果我創建了固定大小的位圖並繪製了更大的路徑,那麼並非所有路徑部分都將被繪製到位圖中,因此如果移動了地圖,某些路徑部分將不可見。如果我創建位圖的路徑大小,我可以運行到一個問題,需要多少內存來創建一個位圖對象,所以應用程序會被殺死。任何想法如何解決它? – Tadas

+0

您可以縮小路徑的大小。用dst矩形將它縮小。這將表現良好,但可能會在較高的縮放級別上缺乏細節,具體取決於位圖的大小。如果你的路徑不經常改變,這個解決方案很好,否則你可能會更好地移除路徑點。 –

0
  1. 您應該知道draw()方法將繪製一個循環約50次。我不知道爲什麼,但你可以測試它。這會降低性能。如果你不得不繪製1000個對象,並繪製()每個繪製30-50 ...它變得非常笨拙.. 爲了避免這種情況,你應該創建一個緩存覆蓋。這個緩存將只繪製所有對象一次,將拒絕其他抽籤。

  2. 爲了加快處理速度,在低優先級的後臺線程中繪製。

  3. 在多點之間繪製直線的最快方法是使用方法Canvas.drawLines(float [] pts,int offset,int count,Paint paint)。 我測試了所有的方法,這是android提供的最快速的方法。

+0

1.您可以指定創建緩存疊加層如何防止繪製運行超過需要嗎? 2.如何在後臺線程中繪製?我知道你可以使用SurfaceView在單獨的線程中繪製或者有另一種方法嗎? – Tadas

+0

1.在位圖中繪製。檢查地圖是否有任何更改(更改的地圖中心,更改的縮放級別等)。如果有任何變化 - 重繪位圖。如果不是,請在屏幕上繪製位圖。 2.我試圖在SurfaceView中繪製,但沒有發生任何事情。您可以創建一個線程類並在UI線程和後臺線程之間創建一個通信模塊。請參閱HandlerThread類。 –