Как сделать рисование маршрута более эффективным? - PullRequest
4 голосов
/ 12 июля 2011

Это код, который я использую для рисования маршрута. Когда у меня 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;
    }
}

}

Ответы [ 3 ]

2 голосов
/ 12 июля 2011

Вы можете нарисовать путь к прозрачному Bitmap объекту (независимо от того, какой размер вы считаете подходящим - чем он больше, тем лучше детализация пути и тем выше потребление памяти).

Убедитесь, что вы создали его с Bitmap.config.ARGB_8888 для прозрачности.

Как только вы это сделаете, вы будете использовать два прямоугольника для отображения пути на Overlay:

  • Исходный прямоугольник, чтобы определить, какая часть пути видима
  • Прямоугольник назначения, чтобы определить, где вы хотите отобразить этот фрагмент пути на холсте Overlay.

Вы будете использовать Canvas.drawBitmap (Растровое изображение, Rect src, RectF dst, Paint paint)

Не должно быть слишком сложно, вы сделали большинство важных вычислений в своем методе transformPath.

Добавлено:

На самом деле вы можете сделать комбинацию как удержания пути, нарисованного на растровом изображении, так и перерисовки фактических точек пути. Используйте описанную выше технику, когда пользователь перемещается по карте или увеличивает / уменьшает, а затем перерисовывает путь, когда пользователь отпускает экран.

0 голосов
/ 13 июля 2011
  1. Вы должны знать, что метод draw () рисует один цикл рисования примерно 50 раз.Я не знаю почему, но вы можете проверить это.Это замедляет производительность.И если вам нужно нарисовать 1000 объектов и draw () рисует их по 30-50 каждый ... это становится очень очень неуклюжим. Чтобы избежать этого, вы должны создать наложение кэша. Этот кэш будет рисовать все объекты только один раз и будетотклонить другие розыгрыши.

  2. Чтобы ускорить процесс, нарисуйте фоновую нить с низким приоритетом.

  3. Самый быстрый способ нарисовать линиюМежду несколькими точками стоит использовать метод Canvas.drawLines (float [] pts, int offset, int count, Paint paint).Я проверил все методы, и это самый быстрый метод, который предлагает Android.

0 голосов
/ 12 июля 2011

Лучший способ увеличить скорость рисования - это уменьшить количество точек, которые включает в себя путь. Вероятно, они не нужны - многие из них просто лежат между предыдущим и следующим, поэтому вы можете отфильтровать их по:

минимальное расстояние от предыдущей точки (простой способ)

минимальное изменение подшипника (немного сложнее, хотя Местоположение класс и его метод bearingTo() должны помочь.

...