MKTileOverlay Tiles disappear after exceeding maximumZ - ios

The tiles are loaded from disk via loadTileAtPath / URLForTilePath with a subclassed MKTileOverlay.
When setting the maximumZ of the overlay, tiles beyond that level are (as expected) no longer loaded. However, the tiles of the level above also disappear. Any ideas?

It's been a while for me, but I had some issues with this in the past. I think it could be something with the internal caching or the overlays.
For example, if it happens to be the case that the tiles disappear at the transition from zoom level 20 to zoom level 21, and it is also the case that your tile source has a maximum zoom level of 20, then the behavior you're seeing could be a result of polylines invalidating portions of MKMapView's rendered tile cache.
It could be that what you're seeing might be happening because your tile source doesn't provide tiles at a high enough zoom level for the amount of zooming you're attempting to do. Normally Apple's MKMapView render cache provides some limited overzooming, but when you do something that triggers a new render (like adding lines), the render cache gets invalidated and the pseudo-overzooming stops working.
However, I also once saw a fix simply by changing the level for the overlay,
Changed from "MKOverlayLevelAboveLabels" to
[mapView addOverlay:overlay level:MKOverlayLevelAboveRoads];
I hope these suggestions can get you a bit further :)

Related

Scaling SVG past unknown threshold causes elements to disappear

I'm using openseadragon with the excellent svg overlay plugin.
On Chrome, the app behaves as expected: users can tap to zoom in until a table rendered in SVG is fully visible, the note on the table is legible.
Here's the link to the demo. Zoom out to see the SVG version of the table appear, overlaying the fuzzy raster version of the background.
On Safari on iOS or OSX when zooming past a seemingly arbitrary threshold the table and everything on it start to disappear. The point of disappearance seems to depend on other factors I don't understand, hence this question for insight. For example, a orange circle drawn with two.js will disappear when the scale transform is precisely 51201 (at 51200 the circle is there). For the more complex table SVG, elements on the table will disappear at different scale levels, between ~23000 to 50000. Sometimes they'll disappear and then reappear upon a slight zoom in. Sometimes they'll disappear on zoom and then reappear as I pan around, the objects nearing the edge of the viewport.
IE 11 has a very similar issue.
Has anyone dealt with this before or solved it?
That's a really slick project!
In my experience, that kind of problem with SVG disappearing has to do with extreme amounts of zoom. The good news is you should be able to work around it by changing your viewport coordinates. By default the width of the image is a viewport value of 1, but you can set your image to be width 10,000 or some such, which will look exactly the same on the screen, but it means that the SVG thinks it's zoomed out a lot at first, so when you zoom in you can go a lot further.
If you're using two.js, another possible fix would be to switch over to canvas rendering and use https://github.com/altert/OpenSeadragonCanvasOverlay.
Btw, I'd love to share your project when it's done... please file a ticket at https://github.com/openseadragon/site-build/issues when you're ready and we can add it to http://openseadragon.github.io/examples/in-the-wild/.

Disable interim tiles for tile layer

When creating a map like this:
var map = new ol.Map({
loadTilesWhileAnimating: true,
loadTilesWhileInteracting: true
})
OpenLayers 3 uses interim tiles (i.e., previously loaded lower resolution tiles) when zooming and panning until it has finished loading the new tiles.
The interim tiles are placed behind the real tiles. Which is very clever, and is great for opaque layers, but much not so great for mostly transparent layers.
We currently have a layer which consists of just a few lines, only a few pixels think. Slightly panning the map makes these into huge blobs, causes a lot of flicker.
Is there a way to disable creating of these interim tiles, just for a specific layer? It would be disappointing if I'd need to disable both loadTilesWhile* properties just because of a single layer.
For an example, see: http://imgur.com/RbtmkpT
The left is normal (the red line is mine), right is after panning slightly.
This is with cacheSize 0 on the source and useInterimTilesOnError false.
Update:
OpenLayers 3.12 behaves differently. In that version, only unloaded tiles are blurry (which is to be expected), but already loaded tiles are left alone. Starting from 3.13 or 3.14, this behavior changed.
See my pull request in the OpenLayers GitHub repository for a solution / workaround:
https://github.com/openlayers/ol3/issues/5251#issuecomment-212322292

How to fix various MKTileOverlay rendering problems?

I'm currently in the process of converting a custom map from using a CATiledLayer scroll view to using custom map tiles in an MKMapView with an MKTileOverlay. Whilst the CATiledLayer-approach generally works well and looks nicer, you get a lot of things for free by using an MKMapView such as rotations which are otherwise very difficult to achieve.
So, I've redrawn my tiles for use with the recommended format of zoom level, column and row numbers, and have them displaying in the map view correctly. Note that my map tiles only cover a small region somewhere; I don't have them for the entire globe.
The first problem I noticed is that there seems to be an issue when you zoom in past the largest zoom level my tiles support. I have tiles all the way to zoom level 20 so I set my MKTileOverlay's maximumZ property to 20. If you zoom in to level 21, the map view no longer requests tiles at all. Any tiles loaded on the way to level 21 still show (albeit pixelated), but if you scroll away it won't load any more tiles, so eventually the map just becomes blank. Ideally, it would fall back to my level 20 tiles and display those instead, or prevent the user from zooming in too far. When I use the CATiledLayer, you could zoom in as much as you want and it would always show the most zoomed in tiles (even if you were zoomed in further than the tiles were 'comfortable' at). Example
I have other minor niggles too:
If you set canReplaceMapContent to true, you can zoom in a lot further (which is fine), but the camera clips the ground if you get too close and I get all sorts of rendering artefacts. Any way to prevent that from happening? Example
Sometimes there are small pixel-sized rendering artefacts between tiles which indicate the tiles aren't quite positioned or sized correctly my the MKMapView. These artefacts don't seem to affect the native maps app; any way to get rid of these? Example
As you pan around when zoomed in, there are a lot of white flashes as tiles are loaded and it's quite obvious. When I used the CATiledLayer, they were loaded in quite smoothly (by animating the opacity) and the lower-zoom levels were already present in the background so it was overall difficult to tell it was even using tiles. Is there any way to load in my tiles more seamlessly? Example
I'm guessing the answer to most of these questions is that it's not possible to fix using MKMapView, which is a shame because I really want to allow the user to change the heading of the map and it seems pretty difficult to do using a standard CATiledLayer!

Synchronize COCOS2D Layer on top of a MKMapView

I'm tring to synchronize cocos2D layer objects with the map, I managed to get it working by adjusting the glView to the visibleMapRect of the MKMapView. I can zoom, move, my objects are following the map. But, there is a small and annoying lag between the MKMapView and the cocos2D Layer.
I'm synchronizing it at each display loop.
Method:
1) Retrieve the MKMapView.visibleMapRect
2) Set the glViewPort
3) Do an orthographic projection to adjust my layer to the MapView.
I already tried others methods, like moving the cocos2D layer with touch and then move the coordinates of my map according to the touch, still laggy.
Even disabling acceleration and deceleration of the MapView doesn't remove the lag.
Thanks.
Shot in the dark: we know that iOS devices use optimizations to speed up rendering while scaling. This is true for Safari browser, when you zoom in you actually only zoom in on the image that is currently being displayed as the browser window's contents. Only after you stop the pinch motion does the device update the view.
You'll see this specifically with text on older devices. When the device re-renders the contents with the new scale factor, the text suddenly becomes sharp and crisp again. I believe the same optimization is done in MKMapView.
You might want to check if the visibleMapRect values are actually updated during the zoom, and whether they accurately reflect the current zoom level or not.
The other issue I can imagine is that the framerate with MKMapView + Cocos2D is simply low. And specifically zooming might consume a lot of CPU power. You might want to enable the cocos2d FPS display to see what the framerate is.
Another trick that's necessary to allow smooth scrolling of views in cocos2d (particularly complex views like UITableView) is to reduce cocos2d's max framerate (animationInterval) and/or to run the rendering of the gl view on a separate thread. Your issue may simply be a variation of this issue: UIScrollView pauses NSTimer until scrolling finishes
Note that this also occurs with DisplayLink director. The info in this question did the trick for me.

Why isn't Quartz double buffering my drawInContext()?

I am rendering a simple line drawing (a line with some text in the middle) in a CALayer subclass via drawInContext(). I update this layer as the user is performing a gesture by calling setNeedsDisplay on it. The effect that I am seeing is what I might expect if there were no double buffering going on... i.e. I see parts of new rendering overlapping parts of old rendering. When I stop updating (complete the gesture) the system "catches up" and I always see the correct final result, but during the updates I see inconsistent results... This effect is not subtle and sometimes it is extreme... e.g. if I keep updating fast enough I can keep stale parts of the drawing on the screen for seconds while the new parts are drawing ahead...
I don't understand this at all. If Quartz is doing buffering then it seems that it is not blitting the result to the screen in its entirety or it is miscalculating the affected area.
Things I've tried:
1) I am disabling implicit animations and doing all of the drawing within a CATransaction
2) I am not making a mistake in my drawing... It's literally just two lines with some text in between... there is no way that I'm rendering the intermediate artifacts.
3) I have tried limiting the rate of updates by skipping most of them... but even at the lower rate I see artifacts until I stop updating and let the system catch up.
4) BTW, this happens identically in the simulator and on the device (iPad).
Is it necessary for me to draw into an offscreen buffer myself and copy it to the screen in its entirety? I thought that I had read that Quartz does this for me.
Update:
As usual, after hours of banging my head against the wall I find the (partial) answer 5 minutes after posting the question. I realized that I was using a CATiledLayer in order to get my layer re-rendered on zoom. If I switch it back to a regular CALayer the glitches go away. So I guess what I am seeing artifacts of the separate tiles rendering. Now I am trying to figure out how to deal with this...
So, it turns out that I had three problems:
1) CATiledLayer explicitly fades in new tile content with a default time of 0.25 seconds... This was causing havoc with my drawing. I overrode this in my CATiledLayer subclass:
+ (CFTimeInterval)fadeDuration {
NSLog(#"got fade duration");
return 0;
}
2) I also had to adjust the maximum tile size up (I set it to 1024x1024 though I don't know what size it is actually using).
3) I was making adjustments to my layer's frame periodically during the updates and that seemed to cause additional problems for the tiled layer. I am making changes to stop that.
With all of those changes the performance seems acceptable now.

Resources