有关使用地面叠加或TileOverlay一些问题,以显示GoogleMap的大覆盖图像地面、图像、问题、TileOverlay

2023-09-06 10:58:14 作者:梦泽

我有一个应用程序,用户可以在谷歌地图的顶部加载图像。这是为2.3开发的,所以存在着显示图像的MapActivity,一个图形页面和我的自定义叠加类。在覆盖类拉伸方法我重新计算矩阵每一次,所以图像获取正确的大小和位置。我也有一个校准模式,其中用户可以通过拖动参考点调整图像

I have an application where a user can load an image on top of a Google map. This was developed for 2.3, so there is a MapActivity, a MapView and my custom Overlay class that shows the image. In the overlay class draw-method I recalculate a Matrix each time, so the image gets the correct size and position. I also have a calibration mode where the user can adjust the image by dragging reference points.

我将某些功能添加到应用程序,我想开始喜欢用碎片一些更新。与MapFragment更换MapActivity带来了一些问题,因为似乎没有成为覆盖在那里你可以自己实现战平任何支持。好像我将不得不使用地面叠加或TileOverlay。 (请纠正我,如果我错了。)

I am going to add some features to the application and I want to start with some updates like using fragments. Replacing the MapActivity with MapFragment brings up some question since there doesn't seem to be any support for overlays where you can implement draw by yourself. It seems like I will have to use GroundOverlays or TileOverlay. (Please correct me if I'm wrong.)

这些都不似乎支持他们已加入后,重叠的任何修改,因此图像的校准将不起作用。我对那部分计划是把一个普通的ImageView的MapFragment用于校准模式上面。 (这将隐藏所有标记,但校准过程中并不重要。)对于这个工作,我需要两件事:*接收影响校准点的所有触摸事件并转发休息,让正常缩放等*发现任何时刻的位置/旋转/缩放级别的变化,所以我可以调整图像。问题1:我可以期待任何大的问题。

Neither of these seems to support any modification of the overlays after they have been added, so the calibration of the image will not work. My plan for that part is to put an ordinary ImageView on top of the MapFragment for the calibration mode. (That will hide all Markers, but that doesn't matter during calibration.) For this to work I need two things: * Receive all touch events that affects the calibration points and forward the rest to allow normal zoom etc. * Detect any time the position/rotation/zoom level changes so I can adjust the image. Question #1: Can I expect any major problems with that?

然后我必须决定是否地面叠加或TileOverlay为preferrable。

Then I have to decide if GroundOverlays or TileOverlay is preferrable.

地面叠加:这似乎是所需要的最少工作,因为它仍然会加载整个图像。我还认为,像屏幕方向自动变化,它会处理事情。问题2:在地面叠加将与大的图像(最大2000 * 2000像素)呢?是否有图像的任何拷贝为何?由于图像是如此之大,我买不起它的多个副本在内存中。

GroundOverlay: This seems to require the least work since it will still load the whole image. I also think that it will handle things like screen orientation changes automatically. Question #2: Will the GroundOverlay work well with a large image (max. 2000*2000 pixels)? Is there any copying of the image involved? Because the image is so large I can not afford more than one copy of it in memory.

TileOverlay:在某种程度上,这似乎是一个更专业的解决方案,因为它仅使用了有实际需要的部分,以后我可以引入使用多个地图图像源在同一时间支持。我可能要产生提前瓷砖和保存每个单独的文件,其保存在内存中,并按需创建瓷砖可能采取的内存。 (或许我可以创建一个单独的瓷砖供应服务,但似乎有点脏。)问题3:是否有过瓷砖缓存将使用多少内存的任何控制?难道平时限制申请?我不想出内存中的应用程序的其他地方,只是因为缓存了大部分我允许使用的内存的运行。问题4:文档说请注意,不像其他的覆盖,如果地图是重建,瓷砖覆盖不会自动恢复,必须手动重新添加。我想,这会发生在每个屏幕旋转,因此,这意味着该文件将不得不再次读取导致noticable加载延迟。有没有解决这个什么好办法?问题5:当getTile叫我返回空值(因为该图块保存在一个文件,我不希望阻止UI线程,而阅读它),如何需要多长时间,直到它再次请求? (似乎没有要手动加载单个拼贴的方式。)问题6:我如何确定一个良好的图像分辨率对于一个平铺图像(相对于性能和质量)

TileOverlay: In a way this seems like a more professional solution because it only uses the parts that are actually needed and I can later introduce support for using several map image sources at the same time. I will probably have to generate the tiles in advance and save a separate file for each, keeping it in memory and creating the tiles on demand might take to much memory. (Or perhaps I can create a separate tile-serving service but that seems a little dirty.) Question #3: Is there any control over how much memory the tile caching will use? Does the usual limit apply? I don't want to run out of memory somewhere else in the application just because the cache took most of the memory I'm allowed to use. Question #4: The documentation says "Note that unlike other overlays, if the map is recreated, tile overlays are not automatically restored and must be re-added manually". I suppose that this will happen on every screen rotation, so that this means that the files will have to be read again causing a noticable loading delay. Is there any good way around this? Question 5: When getTile is called and I return null (because the tile is saved in a file and I don't want to block the ui thread while reading it), how long will it take until it is requested again? (There doesn't seem to be a way to load an individual tile manually.) Question 6: How do I determine a good image resolution for one tile image (with respect to performance and quality)?

推荐答案

的问题很多。我会尽力解决一些。

Lots of questions. I'll try to address some.

一般情况下,提防地图API V2比V1宽容得多。而且这是一件好事。 V2有V1没有更多的内置功能和优化,通过一种严格的API强迫你使用它的优化。

Generally, beware that Maps API v2 is much less permissive than v1. And it's a good thing. v2 has many more built-in functions and optimizations that v1 didn't have, and by having a restrictive API forces you to use its optimizations.

例如,如果你使用的GroundOverlay显示图像[假设你不需要旋转或歪曲],你只需要指定它和地图V2的纬度/长边界时,将拉长像你。 2000×2000会2000x2000x4字节,因此在内存16MBytes。但是的GroundOverlayOptions使用BitmapDesc​​riptor,所以也许它永远不会完全加载在内存中的图像。我不是很熟悉的地面叠加。

For example, if you were using GroundOverlay to display an image [assuming that you don't need to rotate or distort it], you need only specify the Lat/Long bounds of it and Maps v2 will stretch the image for you. 2000x2000 would be 2000x2000x4 bytes so 16MBytes in memory. But GroundOverlayOptions uses a BitmapDescriptor, so maybe it's never fully loading the image in memory. I'm not very familiar with the GroundOverlay.

另一种选择是减少图像中的瓷砖你第一次加载它并将其保存到本地存储,那么它的pretty直向前TileOverlay使用。你不能合理地从2kx2k图像直接读取的瓷砖,因为它会涉及读这一切(如COM pressed,我想这是)。要是你需要显示图像的修改版本,请记住,你只需要在创建位图一个Canvas,它的可变后保证。

The other option is to cut the image in tiles the first time you load it and save them on the local storage, then it's pretty straight-forward to use with TileOverlay. You can't reasonably read the tile directly from the 2kx2k image because it would involve read it all (if compressed, which I guess it is). If ever you need to show a modified version of the image, remember that you only need to create a Canvas over the Bitmap, after ensuring it's mutable.

我更熟悉TileOverlay我用了很多。瓷砖缓存看起来很公平,我已加载的256×256瓦片大金额和总呆在13M和20M堆之间。我认为这是使用相同谷歌地图图块,一些缓存在本地存储内存,但永远不嫌多,并且在没有显示内存瓷砖不缓存的。填充的瓦片被重新加载时,你可以看到。

I'm more familiar with the TileOverlay which I use a lot. The tiles cache looks fair enough to me, I have loaded big amounts of 256x256 tiles and always stayed between 13M and 20M heap. I think it's using the same as for google map tiles, caching some on the local storage memory but never too much, and not caching at all in memory tiles that aren't shown. You can see when padding that the tiles are being reloaded.

您可以轻松地列出你的内部存储的文件看GMaps实现瓷砖的缓存策略。在那里,你会看到GMaps实现缓存瓷砖。

You can easily see GMaps tiles caching strategy by listing the files of your internal storage. There you'll see GMaps caches tiles.

是的,当停止/启动的GoogleMap将调用getTile(X,Y,缩放),对每个显示瓦。貌似每次调用getTile都有自己的线程,所以加载时间ins't的问题。如果你的地砖已经存储在设备上它非常快速加载。真的不是一个问题,只要你存储在一个巧妙的方法您的数据。

Yes, when stop/starting the GoogleMap will call getTile(x, y, zoom) for each showing tile. Looks like each call to getTile has its own thread, so loading time ins't an issue. If your tiles are already stored on your device it's very fast to load. Really not an issue, provided that you store your data in a smart way.

我从来没有返回null。不知道在这种情况下会发生什么。也许它激发了被忽略的异常。请注意,在getTile您code产生的任何运行时异常,甚至有些java.lang.error将GoogleMap的被忽略来电......我报发布在这里,你可能要应用补丁来简化开发:https://$c$c.google.com/p/gmap...

I've never returned null. Don't know what happens in this case. Maybe it fires an exception that is ignored. Note that any runtime exception or even some java.lang.error generated by your code in getTile will be ignored by GoogleMap calls... I've reported to issue here and you might want to apply the patch to ease your development: https://code.google.com/p/gmap...

要回答你的问题,我已经返回NO_TILE对象,然后GMAP缓存它像任何瓷砖。你可以通过调用TileOverlay.clearTileCache().

To reply to your question, I've returned the "NO_TILE" object, and then GMap caches it like any tile. You can force reloading of the tiles by calling TileOverlay.clearTileCache().

我一直在想的,但我只用256×256地砖,似乎即使在高DPI的Nexus 10,不够好我还没有研究这个问题要多得多,但它可能是GMaps实现已选瓷砖这将是最好根据不同的缩放级别显示,只要256p是一个相当标准的瓷砖大小。

I've been thinking of that, but I use only 256x256 tiles and it seems good enough even on the High DPI Nexus 10. I haven't investigated the issue much more, but it might be that GMaps already chooses which tiles would be best to show depending on the zoom level, provided that 256p is quite a standard tile size.