在Android谷歌地图上绘制超过4K个折线

7
我正在开发一款适用于Android设备的应用程序。主要功能是在地图上绘制折线以显示城市中每条街道的交通情况。不幸的是,当我绘制大约3K条折线时 - 数量会根据屏幕大小和缩放级别而减少 - 我的地图变得非常慢...更不用说绘制所有线条所需的时间了。
也许您知道更有效的标记街道或在地图上绘制线条的方法?
我也考虑过切换到OSM,但我从未使用过它,也不知道它的效率如何。
我在三星Galaxy Note 10.1上调试应用程序,并使用Map API v2进行绘制折线的代码如下:
Polyline line;
List<Float> coordinatesStart;
List<Float> coordinatesEnd;
LatLng start;
LatLng end;
List<List<Float>> coordinates;
int polylinesNumber = 0;
for(Features ftr : features){
    coordinates = ftr.geometry.coordinates;

    for(int i = 0; i<coordinates.size()-1; i++){

            coordinatesStart = coordinates.get(i);
            coordinatesEnd = coordinates.get(i+1);
            start = new LatLng(coordinatesStart.get(1), coordinatesStart.get(0));
            end = new LatLng(coordinatesEnd.get(1), coordinatesEnd.get(0));
            line = map.addPolyline(new PolylineOptions()
             .add(start, end)
             .width(3)
             .color(0x7F0000FF)); //semi-transparent blue
            polylinesNumber++;

    }
}

我需要任何帮助!


尝试使用更少浪费的数据结构,例如List<List<Float>>可以改为List<float[]>。并且在可能的情况下尽量共享对象(每行是否都需要自己的PolylineOptions()?难道一个不是足够吗?)。 - Durandal
我认为这个解决方案只会改善绘制时间。但是当线条已经绘制好时,地图的响应能力如何?不幸的是,对于每条线,我都需要选择3种颜色之一,这就是为什么我需要PolylineOptions()的原因... - Krzysztof Jackowski
4个回答

5

优化得很好:

您的主要错误是为每条线绘制使用一个新的PolyLineOptions实例,这使得绘图非常缓慢。

解决方案是:

只使用一个Polyline选项实例,并仅在循环内使用.add(LatLng)函数。

    //MAGIC #1 here
    //You make only ONE instance of polylineOptions.
    //Setting width and color, points for the segments added later inside the loops.
    PolylineOptions myPolylineOptionsInstance = new PolylineOptions()
            .width(3)
            .color(0x7F0000FF);

    for (Features ftr : features) {
        coordinates = ftr.geometry.coordinates;

        for (int i = 0; i < coordinates.size(); i++) {

            coordinatesStart = coordinates.get(i);
            start = new LatLng(coordinatesStart.get(1), coordinatesStart.get(0));

            //MAGIC #2 here
            //Adding the actual point to the polyline instance.
            myPolylineOptionsInstance.add(start);

            polylinesNumber++;
        }
    }

    //MAGIC #3 here
    //Drawing, simply only once.
    line = map.addPolyline(myPolylineOptionsInstance);

注意:

如果你想为不同的线段/区域使用不同的颜色,你需要使用多个多段线选项,因为每个多段线选项只能有一种颜色。但方法是相同的:尽量使用较少的多段线选项。


1
这完全解决了我的问题。之前绘制我的大型折线需要约20秒,现在不到一秒就能完成了。 - Ulrich Scheller
当缩放改变时,折线消失了。有什么解决方法吗? - Rishabh Srivastava
我猜你是不小心删掉了那些? - Adam Varhegyi

3

您是否检查您绘制的折线是否在用户屏幕上可见?如果没有,这将是我的第一个想法。这个问题可能会对此有所帮助。


折线在屏幕上可见,这不是问题。 - Krzysztof Jackowski
我想知道你对成千上万的折线做了什么,因为用户无法处理那么多的信息。也许你可以发布一张地图“实时运行”的截图? - fweigl
问题在于,当我想标记街道时,我必须将线条切成小块以制作曲线等,这就是为什么有那么多元素的原因。 在这里,您可以看到正在运行的Web应用程序: [链接](http://imageshack.us/f/194/screenshot2013052710544.png/) 这是我的Android应用程序: [链接](http://imageshack.us/f/547/screenshot2013052710544.png/) 您可以看到只有很少的街道被标记,已经有大约3000行。 - Krzysztof Jackowski
我认为你不需要成千上万的折线来正确显示这些街道。我建议大幅降低街道的精度,例如,如果你有一条由500个点(和它们之间的折线)组成的街道,只需取每5个或10个点,然后绘制折线。当用户放大时,仍然可以重新绘制更精确的街道。 - fweigl
谢谢大家的回答。我正在考虑按照你们建议改进我的算法,但我想问一下是否有人对解决这个问题有不同的想法。再次感谢您的帮助! - Krzysztof Jackowski

2

我想对此发表意见,因为我觉得这个答案不够完整。如果你放大地图,屏幕上仍会有大量的单独折线,这会导致UI线程停滞。我使用自定义的TileProvider和我的LatLng点到屏幕像素的球形墨卡托投影来解决这个问题。这个想法来自map-utils-library,它具有编写画布到瓦片(以及许多其他好处)所需的大部分工具。

我写了一个示例ComplexTileOverlays,是从我正在开发的项目中提取出来的。这包括在CustomTileProvider中更改透明度和线条粗细的方法。

我首先使用闪屏加载我的自定义折线数据库(对于此示例,它是蒙特利尔岛上自行车设施的开放数据库)。然后,我在一个256x256像素的画布上绘制每条线的投影,表示一个瓦片。总体而言,如果您有很多图形叠加到地图上,这种技术比其他技术快得多。



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接