1

我有一个path()从 json 对象创建的。我将 JSON 对象传递给构造函数中的覆盖对象。

扩展的对象Overlay总是draw()在地图移动、渲染、触摸等任何事情时调用。即使您的叠加层不可见或附近或任何东西。

我想在 for 循环中生成我的路径对象,实际上是一个嵌套循环,因为 json 对象包含嵌套的 json 数组。这有很高的理论计算时间,所以我不想在draw()方法中这样做。相反,我尝试在构造函数中执行逻辑,制作path()文件,然后在draw()此处需要的方法中仅调用该路径文件一次canvas.drawPath(path, mPaint);

不幸的是,当我在构造函数中创建路径时,它不会随地图平移。但是当我在方法中创建它时,完全相同的代码,draw()它确实具有所需的功能:一条围住地图一部分的路径。

问题是该draw()方法将一遍又一遍地调用我的双重 for 循环,并且性能损失是显而易见的并且令人衰弱。即使将循环放在new Thread()draw() 中也无助于提高性能。在构造函数中运行它是理想的,但路径不会随地图平移。

同样,在方法中放置一个私有布尔翻转draw(),以使所需的代码只运行,也不起作用。除非不断地重新绘制路径,否则路径不会出现在地图上,这是一项艰巨的任务。

这个网站上关于这个问题的其他答案的问题是人们正在制作正方形、圆形和图像,它们只需要在 内调用一次draw(),而不是循环来生成路径。

建议?该方法的某些内容draw()有助于叠加层粘在地图上,我怎样才能只运行一次 for 循环

4

2 回答 2

2

给你一些注意事项:

  1. 你不应该覆盖 draw() 方法。Overlay 类已经为您处理了整个平移操作。阅读您会找到的文档。

  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

尽管您已经接受了答案,但我使用的方法如下。在下面的示例代码中,我使用的是 old MapView,但这个概念应该适用于任何版本。我也将它与mapforges(最小调整)一起使用。

概念

  • path在第一次通话时建立你draw(),并记录点的位置(0)
  • 在下一个draw()如果点(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); 
}

每次缩放更改时都必须构建路径。缩放变化检测是使用 pathInitialLonSpan 完成的,因为 getZoomLevel() 与地图缩放动画不同步。

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 回答