Disable interim tiles for tile layer - openlayers-3

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

Related

in layer based drawing how can we reduce the lag while drawing or zooming UIView?

I'm working on a drawing app where every bezier path is CAShapelayer and I'm adding these sub-layers on super layer UIView(CALayer), once the points/lines exceed a certain threshold eg: 1000 CAShapelayer then the drawing, zoom, and scroll lags, is their a way to optimize this?
Couple options for trying to use thousands of layers...
First, I ran a test on a 3rd-gen iPad Pro, generating 8100 shape layers. While there was a little bit of "lag" when zoomed-out to see the full view, it certainly did't make it unusable... and I notice little to no lag when zoomed in.
Second, instead of using shape layers, you could define your own "layer" struct - tracking path, fill, border, etc. Then override draw() and only draw the paths where their bounding box intersects the draw rect.
Third, instead of using a thousands-of-layers view in your scroll view, use maybe an image view. Each time you add a new layer, draw that layer to the image in the image view. As you zoom it will become fuzzy... so each time the user ends zooming, update the image at the new scale. You'll notice a slight lag as the fuzzy image becomes clear, but that will only happen at the end of the zoom. You could even alleviate that by using "stepped" zooming - such, 100%, 200%, 400%, 800%.
Edit
I put together an Example app that:
generates 95 paths, using the Glyphs for chars "!" through "~" from Times New Roman font
paths have min 4 points, max 115 points; min 0 curves, max 55 curves
we add 33,805 CAShapeLayer (not text) layers, using 6 fill/stroke color combinations, to a 3508 x 2480 view in a scroll view
On an old iPhone 7 running iOS 13.3 ... sure, it has a "little" lag, but not what I would call unusable.
Looks like this at 1.0 Zoom Scale:
You may want to take a look at it and see if it has the same "lag" you're experiencing - https://github.com/DonMag/ShapeLayersWork
Edit 2 - 8137 layers using your hand-drawn "a" path:
Edit 3
"Chalkduster" font
generate a "grid" to fill the 3508 x 2480 view
cycle through paths
put all paths of the same color on the same layer (so 6 layers)
Here's the output:
It took over 20-seconds for the view to become visible, and, as we would expect, it's completely unusable.
The "Points: / Curves:" lines list the number of points and curves per layer -- 4-million points and almost 2-million curves. I really think you're going to need to re-think your whole approach.
As a side note... are you familiar with the Sketch App for Mac? I put some text on some layers, using Chalkduster... converted the layers to outlines (paths instead of text)... and even with a small number of layers Sketch performance gets bad.

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!

How to disable showing a layer while changing resolution (e.g. zoom animation) in OL3?

While changing zoom factors for a map, its layers appear stretched with the latest available data, i.e. lower resolution tiles, images, etc.
Is it possible to disable this effect? I would like to have the layer shown only after its "loadend", but the layer's data will be loaded only if it's visible...
I've digged into the rendering workflow, but it's nto easy to find a consistent way to obtain it for all the renderers.

Is it wise to export a Tiled layer into 1 big png file to save memory?

I just made the background layer in Tiled for my map for Sprite Kit. The main layer is the background layer where the grass, dirt, water & the lot is drawn - this what the player character "walks on". This map is consisted of tiles that are 16x16 (keeping them this small for having better control over the little details during design of the map). The map it self is 100x100. So it's pretty decent size wise. I have roughly between 757-778 nodes just because of these background tiles. That's too much and I haven't even added a single tree to the second layer. Since I'm using Tiled as the map editor with JSTileMap to display it, can I just somehow export the ready background layer from Tiled into a .png file and load that into the game as 1 big picture to drop the node count to 1. Wouldn't this drastically help performance and memory? The others layers have their images spread across & there's a layer that's responsible for the boundaries. Is this a clever way of going about making the game or am I missing something? If it is, does anyone know how to export the layer into a .png file? I checked Tiled & couldn't find anything like that.
You are most definitely better off having a single PNG/node as your background. There are some benefits of doing this:
You have just one node.
You can add the node to self and place it behind the rest of the action. This way it will always be there regardless of you moving any other nodes.
In the picture below I added a background to the view and have 3 other tile layers plus 1 object layer. My node count is still substantially less than 700.
As for exporting what you already have, I don't think there's a way to save an entire tile layer as one PNG. As a hack you could take a screenshot, crop the background part and work with that.

Efficient custom tiled maps with custom zoom levels and zoom factors

I have to implement a very custom tiled map layer/view on iOS5/6 (iPhone), which loads tiles as Images and/or data (JSON) from a server. It is like google maps, but at certain points very specific, so I cannot easily use a solution such as:
google maps or
route-me (used by MapBox)
CATiledLayer in combination with UIScrollView
The thing is: None of the solutions out there really do help me, because of my specific specs. If you think, there is a suitable solution, please tell me!!!
If not:
Help me to find the best possible solution for my case!!!
"But why can I not use these beautiful solutions?"
There are a few limits, that have to be known:
We only use 3 zoom-levels (0,1 and 2)
Every tile has a number of 9 subtiles in the next zoomlevel (= zoom factor 3) (not like most of the other kits do with 4 subtiles = zoomfactor 2)
The first layer has an initial size of (speaking in pixels / points is the half) 768*1024.
The second layer is three times wider and higher (zoomfactor 3!!!) -> 2304*3072
The third layer is equally wider and higher than the 2nd -> 6912*9216
Each tile that comes from the server is 256x256 pixels
So every sublayer 9-times the number of tiles (12 on 1st layer, 108 on 2nd, 972 on 3rd)
Every tile has a background image (ca. 6KB in size) (loaded as image from the server) and foreground-information (loaded as JSON for every tile from the server - 10-15KB in size)
-> the foreground information JSON contains either an overlay image (such as traffic in google) or local tile information to be drawn into the local tile coordinate space (like annotations, but per tile)
I want to cache the whole background-tiles on disk, as they never change
Either I want to cache the overlay-tile-images/overlay-tile-information for each tile for a certain amount of time, until it should be reloaded again
Zooming should be with pinching and double-tapping
A few of my considerations:
The caching is not the problem. I do it via CoreData or similar
I thought of a UIScrollView, to show smooth scrolling
I'd like to use pinching, so every time I break through the next zoomlevel, I have to draw the next zoom-level tiles
The content should only be drawn in the visible area (for me on iPhone 5 320x500)
Not visible tiles should be deleted, to be memory efficient. But they should not be deleted instantly, only if a tile is away a certain amount of pixels/points from the visible center. There should be a "display-cache", to instantaneously show tiles, which were just loaded and displayed. Or is there a better technique out there?
I can load the background instantly from disk or from the server asynchronously, as I know which tiles are visible. So do I with the tile-JSON. Then I extract the JSON-information for the tile ("is the overlay a direct image or information such as a city name, which I have to draw into the tile") and draw or load the overlay (from DB/Disc or Server)
Is UIScrollView efficient enough to handle the max size of the tile view
Should I use a CALayer as sublayer to draw into it? Should I use Quartz to draw directly on a big "canvas"?
Now it's your turn !!!
Apple has an example that shows zooming into a single image very deep. They use a CATiledLayer for this.
The example can be found here: http://developer.apple.com/library/ios/#samplecode/PhotoScroller/Introduction/Intro.html
The example works with subtiles that are stored on the phone but maybe it can be adapted to your problem.
I have used my own TiledLayer implementation for these type of non-standard tiling issues that CATiledLayer does not support (and because CATiledLayer still has some unsolved bugs).
That implementation is now available on Github.
Fab1n: this is same implementation that I already sent you by e-mail.
I came up with a very neat and nice solution (custom TiledLayer implementation):
I don't use CATiledLayer as contentView of the scrollView anymore. Instead I added a CALayer subclass to it and added my tiles to it as sublayers. Each tile contains the tile bitmap as contents. When zooming in with the scrollview I switch tiles manually based on the current zoomlevel. Thats perfect!!!
If somebody wants to know details of the implementation -> no problem, write a comment and I post it here.
EDIT:
Details about the implementation:
The implementation in fact is really easy:
Add a UIScrollView to your View/Controller View
Add a UIView (from now on referred to as tileView) as contentView to the ScrollView - same size as ScrollView size (this is completely zoomed out mode - factor 1)
Activate zooming (I had minimum zoom factor 1 and max. 9)
When you now place an image into the tileView, zooming into level 9 will give as a very unsharp pixelated image - that's what we want (I'll explain why)
If you like crisp clear images when you zoom in, you should add CALayer instances (tiles) with addSublayer: to tileView
Assuming you have a zoomFactor of 3 (I had - meaning 1 Tile in layer 0 - zoomFactor 1 will consist of 3x3 = 9 tiles in layer 1 - zoomFactor 3)
In layer 0 say you put 3x4 tiles with 243x243 (3 times devidable by 3) pixels (as sublayers to tileView). You put your same size tile images as CALayer contents. Zooming to zoomFactor 3 makes them blurry (like old google maps)
When you hit zoomFactor 3 remove all 12 layers from superlayer and replace them with 3 times smaller ones (81x81 pixels). You get 9 times more layers in a whole.
Now that you have 3 times smaller tile layers, the trick is the .contents property of CALayer. Even if the layer is 81x81, the contents (your image) are still full resolution, meaning if you put a 243x243 pixels image as contents of your 81x81 pixels CALayer tile, on zoomFactor 3 it looks like a 243x243 pixels tile!!!
You can go with that on any zoomFactor (3,9,12) deeper. The tiles get smaller and smaller, but setting the original image as contents, the tile will look crisp and sharp at the exact zoomFactor they are placed in.
If you like your tiles look sharp even between the zoomFactors, you have to set a 3 times taller image as .contents. Then your tile is crisp and sharp even short before you're passing the next zoomLevel.
The one thing you have to figure out is, removing all tiles on a layer when passing the zoomLevel factor is not efficient. You only have to update the visible tiles in rect.
Not the nicest of all solutions, but it works and if someone does a well designed library maybe there is potential for this to be a clean solution.

Resources