sim*_*dam 5 optimization performance android google-maps android-mapview
我试图解决从巨大的(100k +)GeoPoints集到Android上的MapView绘制路径的问题.首先,我想说,我通过搜索StackOverflow上很多,并没有发现我的代码的answer.The瓶颈不是实际绘制到画布上,但Projection.toPixels(GeoPoint, Point)还是Rect.contains(point.x, point.y)method..I我跳过在屏幕上不可见的点,也仅显示根据当前缩放级别每第n个点.当地图放大时我希望显示尽可能准确的路径,所以我跳过零(或接近零)点,这样当找到可见点时,我需要为集合中的每个点调用投影方法.这真的需要花费很多时间(不是几秒钟,但地图平移不流畅,我不是在HTC Wildfire上测试:)).我尝试缓存计算点,但由于在每次地图平移/缩放后重新计算点数,它根本没有帮助.
我想过使用某种修剪和搜索算法而不是迭代数组,但我发现输入数据没有排序(我不能扔掉任何堆叠在两个不可见点之间的分支).我可以在开始时通过简单的排序来解决这个问题,但我仍然不确定即使是对数计数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);
}
Run Code Online (Sandbox Code Playgroud)
所以我想出了如何让这一切变得更快!我将其发布在这里,将来可能有人会发现它有用。事实证明,使用projection.toPixels()确实会损害应用程序性能。所以我发现这种方法比获取每个单个GeoPoint,将其转换为Point然后检查它是否包含在地图视口中更好,当我按如下方式计算地图的实际视口半径时:
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);
Run Code Online (Sandbox Code Playgroud)
半径在 results2[0] 中..
然后我可以取出每一个GeoPoint并计算它与地图中心之间的距离mapView.getMapCenter()。然后我可以将半径与计算出的距离进行比较,并决定是否不显示该点。
就是这样,希望对您有所帮助。