Renderer abstract class
An abstract strategy class for rendering a grid of image tiles covering the map viewport.
abstract class Renderer {
TileLayer _layer;
/// Creates a renderer for a tile [_layer]
Renderer(this._layer);
/// Invoked by a [TileLayer] to render itself
void render() {
beforeRender();
renderTileGrid();
afterRender();
}
/**
* Invoked before the tile grid is rendered using [renderTileGrid].
* Default implementation is empty. Override in subclasses if
* necessary.
*/
void beforeRender(){}
/**
* Renders the tile grid
*/
void renderTileGrid() {
var map = _layer._map;
var tileSize = _layer.tileSize;
var centerOnZoomPlane = map.mapToZoomPlane(map.earthToMap(map.center));
var vshalf = (map.viewportSize / 2).toInt();
var topLeftOnZoomPlane = new Point2D(
centerOnZoomPlane.x - vshalf.width,
centerOnZoomPlane.y - vshalf.height
);
var viewportOnZoomPlaneBounds = new Bounds(
topLeftOnZoomPlane,
topLeftOnZoomPlane + map.viewportSize
);
tileIntersectsWithViewport(Point2D t) {
var tl = t.scale(sx:tileSize.width, sy:tileSize.height);
var tileBounds = new Bounds(
tl,
tl + tileSize
);
return viewportOnZoomPlaneBounds.intersects(tileBounds);
}
// the tile covering the map center
var tile = new Point2D(
centerOnZoomPlane.x ~/ tileSize.width,
centerOnZoomPlane.y ~/ tileSize.height
);
// find the first tile to be rendered
while(true) {
var candidate = tile.translate(dx:-1);
if (candidate.x < 0) break;
if (! tileIntersectsWithViewport(candidate)) break;
tile = candidate;
}
while(true) {
var candidate = tile.translate(dy:-1);
if (candidate.y < 0) break;
if (! tileIntersectsWithViewport(candidate)) break;
tile = candidate;
}
// render the tile grid intersecting with the viewport
var maxTileX = (1 << map.zoom);
var maxTileY = (1 << map.zoom);
var cur = new Point2D.from(tile);
while(cur.x < maxTileX && tileIntersectsWithViewport(cur)) {
while(cur.y < maxTileY && tileIntersectsWithViewport(cur)) {
renderTile(cur);
cur = cur.translate(dy:1);
}
cur = new Point2D(cur.x + 1, tile.y);
}
}
/**
* Invoked after the tile grid is rendered using [renderTileGrid].
* Default implementation is empty. Override in subclasses if
* necessary.
*/
void afterRender(){}
/**
* Renders the tile at position [tileCoord] in the current
* tile plane.
*/
void renderTile(Point2D tileCoord);
}
Subclasses
CanvasRenderer, ImgGridRenderer
Constructors
Methods
void afterRender() #
Invoked after the tile grid is rendered using renderTileGrid. Default implementation is empty. Override in subclasses if necessary.
void afterRender(){}
void beforeRender() #
Invoked before the tile grid is rendered using renderTileGrid. Default implementation is empty. Override in subclasses if necessary.
void beforeRender(){}
void render() #
Invoked by a TileLayer to render itself
void render() {
beforeRender();
renderTileGrid();
afterRender();
}
abstract void renderTile(Point2D tileCoord) #
Renders the tile at position tileCoord in the current tile plane.
void renderTileGrid() #
Renders the tile grid
void renderTileGrid() {
var map = _layer._map;
var tileSize = _layer.tileSize;
var centerOnZoomPlane = map.mapToZoomPlane(map.earthToMap(map.center));
var vshalf = (map.viewportSize / 2).toInt();
var topLeftOnZoomPlane = new Point2D(
centerOnZoomPlane.x - vshalf.width,
centerOnZoomPlane.y - vshalf.height
);
var viewportOnZoomPlaneBounds = new Bounds(
topLeftOnZoomPlane,
topLeftOnZoomPlane + map.viewportSize
);
tileIntersectsWithViewport(Point2D t) {
var tl = t.scale(sx:tileSize.width, sy:tileSize.height);
var tileBounds = new Bounds(
tl,
tl + tileSize
);
return viewportOnZoomPlaneBounds.intersects(tileBounds);
}
// the tile covering the map center
var tile = new Point2D(
centerOnZoomPlane.x ~/ tileSize.width,
centerOnZoomPlane.y ~/ tileSize.height
);
// find the first tile to be rendered
while(true) {
var candidate = tile.translate(dx:-1);
if (candidate.x < 0) break;
if (! tileIntersectsWithViewport(candidate)) break;
tile = candidate;
}
while(true) {
var candidate = tile.translate(dy:-1);
if (candidate.y < 0) break;
if (! tileIntersectsWithViewport(candidate)) break;
tile = candidate;
}
// render the tile grid intersecting with the viewport
var maxTileX = (1 << map.zoom);
var maxTileY = (1 << map.zoom);
var cur = new Point2D.from(tile);
while(cur.x < maxTileX && tileIntersectsWithViewport(cur)) {
while(cur.y < maxTileY && tileIntersectsWithViewport(cur)) {
renderTile(cur);
cur = cur.translate(dy:1);
}
cur = new Point2D(cur.x + 1, tile.y);
}
}