Skip to content

Bottlenecks and pitfalls

Jan Marsch edited this page Aug 28, 2014 · 2 revisions

Data

Data tile loading works generally fine. The visual impact of tiles not/being loaded is quite low and could be further decreased by adding buffer to the viewport extending.

CartoDB API could be improved by allowing different id columns. Especially valuable with OSM data. It could also be extended to handle CDN subdomains and as well as better SQL WHERE filtering.

For any GeoJSON data, standard defines the id property to be feature.id instead of feature.properties.cartodb_id. Maybe an addition.

Worth noting, the CartoDB data importer doesn't handle GeoJSON GeometryCollections yet.

Also have a look into this very informative blog post about canvas vector tile rendering. Most points apply to VECNIK. http://chairnerd.seatgeek.com/high-performance-map-interactions-using-html5-canvas/

Rendering

So far, rendering happens per tile, with one canvas each. There are multiple passes per selector and geometry type. Stroke and fill within one pass are a single operation. Nevertheless, complex rules cause lots of rendering passes. I.e. layer with red fill, one with green fill and one with yellow fill will all be painted. It makes some sense, as we don't know about alpha and size transforms.

Idea: maybe there should be a very strict limit of one stroke and one fill operation. Everything else could fall back to Mapnik.

For optimization it's essential to prepare data server side. There should be proper simplification, but also combination of joint geometries where applicable. I.e. OSM highway data had been splitted into thousands of segments. That was too many draw operations, too many memory objects and for interaction, pieces are difficult to hit.

Label placement

In order to place markers and labels, every geometry can be transformed into its centroid point. In case there are just a few tiles of a larger geometry available, only these are taken into account and the label seems misplaced. It might be good for the moment but odd, when you start panning and zooming. Positions are kept stable across zoom levels. A proper cleanup of positions from unloaded tiles could be implemented.

Label and marker collisions are solved via a basic lookup list of bounding boxes. This should be at least turned into a QuadTree. Cut labels and markers can only be avoided by extending the data buffer around a tile.

Interaction

Hit detection is precise and fast. Rendering hover states is rather difficult as we need to look up and redraw all affected tiles. Applies also to previously highlighted ones. In order to speed up activation, it's maybe worth to draw onto a separate canvas on top of all. CCSS rules do not enforce that but maybe we can restrict to that behavior.

JS API

As far as I understood, the API is meant for retrieving and manipulating objects. Notice: event payload has to be an API wrapped feature.

Selectors are rather simple to do:

.filter({ cartodb_id: 80714 })
.filter({ highway: 'motorway' })
.filter(function(item) { item.size < 173 })

Styling is fine too, but causes a full redraw on all (affected) tiles.

.style({ 'line-width': 10 });

Animations / Transitions

This is, where VECKNIK could excel.

> .fadeOut();
> .animate({ scale: 3 })
> .animate({ 'polygon-fill': '#333' });

jQuery has a nice API http://api.jquery.com/animate/

But things get really ugly.

Bad

Every animation step causes a redraw of all affected tiles. A single redraw with many rules on a tile can be already very costly. But this, at least 25 fps will kill it.

Worse

A scale, translation or rotation likely changes the number of affected tiles. That multiplies the issues of 'Bad'. Furthermore: the exact position of an animated item on a newly affected tile has to be determined.

As a solution, we can maybe draw onto a separate topmost canvas as well.

Optimization

I would suggest to restrict the number of rendering passes to geometry objects. One pass for points, lines, polygons, labels each. Propably worth considering: split the passes into individual stacked canvases.

If acceptable, all dynamic drawings in a viewport sized canvas on top of everything.

Clone this wiki locally