CpuTileRenderer¶
Namespace: ThinkGeo.Core
Renders vector tiles, styled by a style.json document, to PNG images without a GPU. Everything before the draw is the GPU map's own pipeline - the tile sources, the style evaluation, the tessellation into buckets - and the buckets are rasterized with the same geometry and the same coverage math the GL shaders use.
public sealed class CpuTileRenderer : System.IDisposable
Inheritance object → CpuTileRenderer
Implements IDisposable
Remarks:
This or GpuTileRenderer. There are two headless renderers for one document, and they are for different machines. This one needs nothing but Skia, which ThinkGeo.Core already carries: no GL, no driver, no ANGLE build shipped beside the application, so a container with no GPU in it draws maps the moment it starts. GpuTileRenderer, in ThinkGeo.Gpu, wants an EGL/GLES pair and is the faster of the two wherever one can be had.
Measured on 12 midtown tiles at z14-16, 512 px, warm tile cache (TileRendererBench, under SimpleSamples\PreludeMvt, which is where to re-measure rather than trust these numbers): drawing each tile once, the median tile costs 306 ms here against GpuTileRenderer's 342 ms on hardware and 484 ms on its software GL backend - fastest of the three on a machine with no GPU, a wash on a machine with one. Drawing the same view over and over it costs 404 ms against the GPU's 31 ms, because this renderer holds no cache whatsoever: every render decodes the tiles, tessellates them and places the labels again. So: distinct tiles - a tile server, a cache warm-up, a batch of images - belong here, and a view that is redrawn belongs on the GPU, which keeps its scene between frames.
What draws: the background, fill, fill-outline, fill-pattern, line (including the dual and super-line composites), circle, symbol - icons and text, placed by the same MapLibre placement engine the GPU map uses - fill-extrusion, and raster layers with the whole of their paint (opacity, brightness, contrast, saturation, hue-rotate, resampling), from the raster sources the style registered or declared. What does not: hillshade and heatmap layers are skipped. The camera is fixed at pitch 0 and bearing 0. In an image (CpuTileRenderer.RenderAsync(PointShape, double, int, int, CancellationToken)) walls on extruded buildings lean away from the view centre exactly as they do on the GPU at pitch 0; a tile (CpuTileRenderer.RenderTileAsync(int, long, long, CancellationToken)) draws extrusions as their roofs, because a tile has a view centre of its own and walls that lean towards it would break at every tile edge once the tiles are laid side by side.
It is also the instrument that holds the two renderers to one document: the gate's cpu-vs-gl and cpu-vs-gl-labels lanes draw a whole city both ways and compare the pixels (0.67-1.70 RMSE over z13-16, which is antialiasing noise). Two independent back ends over one style is what keeps one document from quietly meaning two different maps.
Methods¶
CreateAsync(IReadOnlyList<IVectorTileSource>, MapStyle, float, LabelDisplayMode, CancellationToken)¶
Opens the tile sources, compiles the style and returns a renderer ready to draw.
public static Task<CpuTileRenderer> CreateAsync(IReadOnlyList<IVectorTileSource> tileSources, MapStyle style, float scaleFactor, LabelDisplayMode labelDisplayMode, CancellationToken cancellationToken)
Parameters¶
tileSources IReadOnlyList<IVectorTileSource>
The vector tile sources the style's layers read, sharing one tile grid. They stay the caller's: disposing the renderer does not dispose them.
style MapStyle
The style to draw with.
scaleFactor float
Device pixels per logical pixel: line widths, circle radii, text and translations in the style are logical pixels and are multiplied by this, and the sprites are compiled for it - 2 for an @2x image. Below 0.5 counts as 0.5.
labelDisplayMode LabelDisplayMode
What every render draws: shapes and labels (the default), shapes only, or labels only.
cancellationToken CancellationToken
Cancels opening and compiling.
Returns¶
RenderTileAsync(int, long, long, CancellationToken)¶
Renders one tile of the tile sources' grid, z/x/y with rows counted from the top: the tile's own pixel size and scale in the grid, times the scale factor in device pixels - a 512-pixel grid at a scale factor of 2 gives a 1024-pixel image of the same tile.
public Task<Byte[]> RenderTileAsync(int zoom, long x, long y, CancellationToken cancellationToken)
Parameters¶
zoom int
x long
y long
cancellationToken CancellationToken
Returns¶
Task<Byte[]>
The PNG-encoded image.
Remarks:
The tile is the grid's own, as GpuTileRenderer.RenderTileAsync reads it: a grid cut over a national projection has a root tile of a few hundred kilometres, not the 40075 km of web mercator's, and a tile cut out of mercator's square lands somewhere else entirely. A source with no grid of its own is web mercator. https://community.thinkgeo.com/t/wms-wfs-feedback-wishes/12476
RenderAsync(PointShape, double, int, int, CancellationToken)¶
Renders the view centered on , in the tile sources' grid coordinates (spherical mercator metres for a web-mercator grid), at , by device pixels.
public Task<Byte[]> RenderAsync(PointShape center, double scale, int width, int height, CancellationToken cancellationToken)
Parameters¶
center PointShape
scale double
width int
height int
cancellationToken CancellationToken
Returns¶
Task<Byte[]>
The PNG-encoded image.
A(PointShape, double, int, int, int, CancellationToken, bool)¶
internal Task<SKBitmap> A(PointShape , double , int , int , int , CancellationToken , bool )
Parameters¶
`` PointShape
`` double
`` int
`` int
`` int
`` bool
Returns¶
Dispose()¶
Releases the raster sources the renderer made from the style. The tile sources passed to CpuTileRenderer.CreateAsync(IReadOnlyList<IVectorTileSource>, MapStyle, float, LabelDisplayMode, CancellationToken) are the caller's and are left open.
public void Dispose()
Returns¶
A(IReadOnlyList<IVectorTileSource>, MapStyle, SKBitmap, RectangleShape, double, float, LabelDisplayMode, int, CancellationToken, IReadOnlyDictionary<string, RasterTileSource>, bool)¶
internal static Task A(IReadOnlyList<IVectorTileSource> , MapStyle , SKBitmap , RectangleShape , double , float , LabelDisplayMode , int , CancellationToken , IReadOnlyDictionary<string, RasterTileSource> rasterSources, bool )
Parameters¶
`` IReadOnlyList<IVectorTileSource>
`` MapStyle
`` SKBitmap
`` double
`` float
`` int
rasterSources IReadOnlyDictionary<string, RasterTileSource>
`` bool
Returns¶
A(IReadOnlyList<IVectorTileSource>, RectangleShape, double, int)¶
internal static ValueTuple<int, int, double, List<MatrixCell>> A(IReadOnlyList<IVectorTileSource> , RectangleShape , double , int )
Parameters¶
`` IReadOnlyList<IVectorTileSource>
`` double
`` int