Transform tile-pixels coordinates only once

This allows us to simplify the vector tile renderer significantly, because
there are no more coordinates that need special tile-pixel handling.
This commit is contained in:
Andreas Hocevar
2017-08-28 19:02:19 +02:00
parent 989b047dc1
commit 4b4f383043
9 changed files with 167 additions and 132 deletions
+29
View File
@@ -2,6 +2,35 @@
### Next Release ### Next Release
#### Minor change for custom `tileLoadFunction` with `ol.source.VectorTile`
It is no longer necessary to set the projection on the tile. Instead, the `readFeatures` method must be called with the tile's extent as `extent` option and the view's projection as `featureProjection`.
Before:
```js
tile.setLoader(function() {
var data = // ... fetch data
var format = tile.getFormat();
tile.setFeatures(format.readFeatures(data));
tile.setProjection(format.readProjection(data));
// uncomment the line below for ol.format.MVT only
//tile.setExtent(format.getLastExtent());
});
```
After:
```js
tile.setLoader(function() {
var data = // ... fetch data
var format = tile.getFormat();
tile.setFeatures(format.readFeatures(data, {
featureProjection: map.getView().getProjection(),
// uncomment the line below for ol.format.MVT only
//extent: tile.getExtent()
}));
);
```
### v4.3.0 ### v4.3.0
#### `ol.source.VectorTile` no longer requires a `tileGrid` option #### `ol.source.VectorTile` no longer requires a `tileGrid` option
+15 -4
View File
@@ -1870,6 +1870,7 @@ olx.format;
/** /**
* @typedef {{dataProjection: ol.ProjectionLike, * @typedef {{dataProjection: ol.ProjectionLike,
* extent: (ol.Extent|undefined),
* featureProjection: ol.ProjectionLike, * featureProjection: ol.ProjectionLike,
* rightHanded: (boolean|undefined)}} * rightHanded: (boolean|undefined)}}
*/ */
@@ -1888,6 +1889,15 @@ olx.format.ReadOptions;
olx.format.ReadOptions.prototype.dataProjection; olx.format.ReadOptions.prototype.dataProjection;
/**
* Tile extent of the tile being read. This is only used and required for
* {@link ol.format.MVT}.
* @type {ol.Extent}
* @api
*/
olx.format.ReadOptions.prototype.extent;
/** /**
* Projection of the feature geometries created by the format reader. If not * Projection of the feature geometries created by the format reader. If not
* provided, features will be returned in the `dataProjection`. * provided, features will be returned in the `dataProjection`.
@@ -5094,10 +5104,11 @@ olx.source.VectorTileOptions.prototype.tileGrid;
* tile.setLoader(function() { * tile.setLoader(function() {
* var data = // ... fetch data * var data = // ... fetch data
* var format = tile.getFormat(); * var format = tile.getFormat();
* tile.setFeatures(format.readFeatures(data)); * tile.setFeatures(format.readFeatures(data, {
* tile.setProjection(format.readProjection(data)); * // uncomment the line below for ol.format.MVT only
* // uncomment the line below for ol.format.MVT only * extent: tile.getExtent(),
* //tile.setExtent(format.getLastExtent()); * featureProjection: map.getView().getProjection()
* }));
* }; * };
* }); * });
* ``` * ```
+1 -1
View File
@@ -38,7 +38,7 @@ ol.format.MVT = function(opt_options) {
* @type {ol.proj.Projection} * @type {ol.proj.Projection}
*/ */
this.defaultDataProjection = new ol.proj.Projection({ this.defaultDataProjection = new ol.proj.Projection({
code: '', code: 'EPSG:3857',
units: ol.proj.Units.TILE_PIXELS units: ol.proj.Units.TILE_PIXELS
}); });
+26 -1
View File
@@ -4,7 +4,10 @@ goog.require('ol');
goog.require('ol.Object'); goog.require('ol.Object');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.functions'); goog.require('ol.functions');
goog.require('ol.geom.flat.transform');
goog.require('ol.proj'); goog.require('ol.proj');
goog.require('ol.proj.Units');
goog.require('ol.transform');
/** /**
@@ -55,6 +58,12 @@ ol.geom.Geometry = function() {
*/ */
this.simplifiedGeometryRevision = 0; this.simplifiedGeometryRevision = 0;
/**
* @private
* @type {ol.Transform}
*/
this.tmpTransform_ = ol.transform.create();
}; };
ol.inherits(ol.geom.Geometry, ol.Object); ol.inherits(ol.geom.Geometry, ol.Object);
@@ -244,6 +253,22 @@ ol.geom.Geometry.prototype.translate = function(deltaX, deltaY) {};
* @api * @api
*/ */
ol.geom.Geometry.prototype.transform = function(source, destination) { ol.geom.Geometry.prototype.transform = function(source, destination) {
this.applyTransform(ol.proj.getTransform(source, destination)); var tmpTransform = this.tmpTransform_;
source = ol.proj.get(source);
var transformFn = source.getUnits() == ol.proj.Units.TILE_PIXELS ?
function(inCoordinates, outCoordinates, stride) {
var pixelExtent = source.getExtent();
var projectedExtent = source.getWorldExtent();
var scale = ol.extent.getHeight(projectedExtent) / ol.extent.getHeight(pixelExtent);
ol.transform.compose(tmpTransform,
projectedExtent[0], projectedExtent[3],
scale, -scale, 0,
0, 0);
ol.geom.flat.transform.transform2D(inCoordinates, 0, inCoordinates.length, stride,
tmpTransform, outCoordinates);
return ol.proj.getTransform(source, destination)(inCoordinates, outCoordinates, stride);
} :
ol.proj.getTransform(source, destination);
this.applyTransform(transformFn);
return this; return this;
}; };
+9
View File
@@ -43,18 +43,27 @@ ol.proj.Projection = function(options) {
this.code_ = options.code; this.code_ = options.code;
/** /**
* Units of projected coordinates. When set to `ol.proj.Units.TILE_PIXELS`, a
* `this.extent_` and `this.worldExtent_` must be configured properly for each
* tile.
* @private * @private
* @type {ol.proj.Units} * @type {ol.proj.Units}
*/ */
this.units_ = /** @type {ol.proj.Units} */ (options.units); this.units_ = /** @type {ol.proj.Units} */ (options.units);
/** /**
* Validity extent of the projection in projected coordinates. For projections
* with `ol.proj.Units.TILE_PIXELS` units, this is the extent of the tile in
* tile pixel space.
* @private * @private
* @type {ol.Extent} * @type {ol.Extent}
*/ */
this.extent_ = options.extent !== undefined ? options.extent : null; this.extent_ = options.extent !== undefined ? options.extent : null;
/** /**
* Extent of the world in EPSG:4326. For projections with
* `ol.proj.Units.TILE_PIXELS` units, this is the extent of the tile in
* projected coordinate space.
* @private * @private
* @type {ol.Extent} * @type {ol.Extent}
*/ */
+33 -3
View File
@@ -3,12 +3,14 @@ goog.provide('ol.render.Feature');
goog.require('ol'); goog.require('ol');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.geom.GeometryType'); goog.require('ol.geom.GeometryType');
goog.require('ol.geom.flat.transform');
goog.require('ol.transform');
/** /**
* Lightweight, read-only, {@link ol.Feature} and {@link ol.geom.Geometry} like * Lightweight, read-only, {@link ol.Feature} and {@link ol.geom.Geometry} like
* structure, optimized for rendering and styling. Geometry access through the * structure, optimized for vector tile rendering and styling. Geometry access
* API is limited to getting the type and extent of the geometry. * through the API is limited to getting the type and extent of the geometry.
* *
* @constructor * @constructor
* @param {ol.geom.GeometryType} type Geometry type. * @param {ol.geom.GeometryType} type Geometry type.
@@ -54,6 +56,13 @@ ol.render.Feature = function(type, flatCoordinates, ends, properties, id) {
* @type {Object.<string, *>} * @type {Object.<string, *>}
*/ */
this.properties_ = properties; this.properties_ = properties;
/**
* @private
* @type {ol.Transform}
*/
this.tmpTransform_ = ol.transform.create();
}; };
@@ -71,7 +80,8 @@ ol.render.Feature.prototype.get = function(key) {
/** /**
* @return {Array.<number>|Array.<Array.<number>>} Ends or endss. * @return {Array.<number>|Array.<Array.<number>>} Ends or endss.
*/ */
ol.render.Feature.prototype.getEnds = function() { ol.render.Feature.prototype.getEnds =
ol.render.Feature.prototype.getEndss = function() {
return this.ends_; return this.ends_;
}; };
@@ -169,3 +179,23 @@ ol.render.Feature.prototype.getStyleFunction = ol.nullFunction;
ol.render.Feature.prototype.getType = function() { ol.render.Feature.prototype.getType = function() {
return this.type_; return this.type_;
}; };
/**
* Transform geometry coordinates from tile pixel space to projected.
* The SRS of the source and destination are expected to be the same.
*
* @param {ol.ProjectionLike} source The current projection
* @param {ol.ProjectionLike} destination The desired projection.
*/
ol.render.Feature.prototype.transform = function(source, destination) {
var pixelExtent = source.getExtent();
var projectedExtent = source.getWorldExtent();
var scale = ol.extent.getHeight(projectedExtent) / ol.extent.getHeight(pixelExtent);
var transform = this.tmpTransform_;
ol.transform.compose(transform,
projectedExtent[0], projectedExtent[3],
scale, -scale, 0,
0, 0);
ol.geom.flat.transform.transform2D(this.flatCoordinates_, 0, this.flatCoordinates_.length, 2,
transform, this.flatCoordinates_);
};
+41 -102
View File
@@ -15,7 +15,6 @@ goog.require('ol.render.replay');
goog.require('ol.renderer.Type'); goog.require('ol.renderer.Type');
goog.require('ol.renderer.canvas.TileLayer'); goog.require('ol.renderer.canvas.TileLayer');
goog.require('ol.renderer.vector'); goog.require('ol.renderer.vector');
goog.require('ol.size');
goog.require('ol.transform'); goog.require('ol.transform');
@@ -156,36 +155,21 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(
if (sourceTile.getState() == ol.TileState.ERROR) { if (sourceTile.getState() == ol.TileState.ERROR) {
continue; continue;
} }
replayState.dirty = false;
var sourceTileCoord = sourceTile.tileCoord; var sourceTileCoord = sourceTile.tileCoord;
var tileProjection = sourceTile.getProjection();
var sourceTileResolution = sourceTileGrid.getResolution(sourceTile.tileCoord[0]);
var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord); var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);
var sharedExtent = ol.extent.getIntersection(tileExtent, sourceTileExtent); var sharedExtent = ol.extent.getIntersection(tileExtent, sourceTileExtent);
var extent, reproject, tileResolution; var tileProjection = sourceTile.getProjection();
if (tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS) { var reproject = false;
var tilePixelRatio = tileResolution = this.getTilePixelRatio_(source, sourceTile); if (!ol.proj.equivalent(projection, tileProjection)) {
var transform = ol.transform.compose(this.tmpTransform_, reproject = true;
0, 0, sourceTile.setProjection(projection);
1 / sourceTileResolution * tilePixelRatio, -1 / sourceTileResolution * tilePixelRatio,
0,
-sourceTileExtent[0], -sourceTileExtent[3]);
extent = (ol.transform.apply(transform, [sharedExtent[0], sharedExtent[3]])
.concat(ol.transform.apply(transform, [sharedExtent[2], sharedExtent[1]])));
} else {
tileResolution = resolution;
extent = sharedExtent;
if (!ol.proj.equivalent(projection, tileProjection)) {
reproject = true;
sourceTile.setProjection(projection);
}
} }
replayState.dirty = false; replayState.dirty = false;
var replayGroup = new ol.render.canvas.ReplayGroup(0, extent, var replayGroup = new ol.render.canvas.ReplayGroup(0, sharedExtent,
tileResolution, source.getOverlaps(), layer.getRenderBuffer()); resolution, source.getOverlaps(), layer.getRenderBuffer());
var squaredTolerance = ol.renderer.vector.getSquaredTolerance( var squaredTolerance = ol.renderer.vector.getSquaredTolerance(
tileResolution, pixelRatio); resolution, pixelRatio);
/** /**
* @param {ol.Feature|ol.render.Feature} feature Feature. * @param {ol.Feature|ol.render.Feature} feature Feature.
@@ -221,6 +205,12 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(
for (var i = 0, ii = features.length; i < ii; ++i) { for (var i = 0, ii = features.length; i < ii; ++i) {
feature = features[i]; feature = features[i];
if (reproject) { if (reproject) {
if (tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS) {
// projected tile extent
tileProjection.setWorldExtent(sourceTileExtent);
// tile extent in tile pixel space
tileProjection.setExtent(sourceTile.getExtent());
}
feature.getGeometry().transform(tileProjection, projection); feature.getGeometry().transform(tileProjection, projection);
} }
renderFeature.call(this, feature); renderFeature.call(this, feature);
@@ -263,10 +253,9 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
var source = /** @type {ol.source.VectorTile} */ (layer.getSource()); var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection); var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
var sourceTileGrid = source.getTileGrid(); var bufferedExtent, found;
var bufferedExtent, found, tileSpaceCoordinate; var i, ii, replayGroup;
var i, ii, origin, replayGroup; var tile, tileCoord, tileExtent;
var tile, tileCoord, tileExtent, tilePixelRatio, tileRenderResolution;
for (i = 0, ii = renderedTiles.length; i < ii; ++i) { for (i = 0, ii = renderedTiles.length; i < ii; ++i) {
tile = renderedTiles[i]; tile = renderedTiles[i];
tileCoord = tile.tileCoord; tileCoord = tile.tileCoord;
@@ -280,25 +269,9 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
if (sourceTile.getState() == ol.TileState.ERROR) { if (sourceTile.getState() == ol.TileState.ERROR) {
continue; continue;
} }
if (sourceTile.getProjection().getUnits() === ol.proj.Units.TILE_PIXELS) {
var sourceTileCoord = sourceTile.tileCoord;
var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord, this.tmpExtent);
origin = ol.extent.getTopLeft(sourceTileExtent);
tilePixelRatio = this.getTilePixelRatio_(source, sourceTile);
var sourceTileResolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
tileRenderResolution = sourceTileResolution / tilePixelRatio;
tileSpaceCoordinate = [
(coordinate[0] - origin[0]) / tileRenderResolution,
(origin[1] - coordinate[1]) / tileRenderResolution
];
var upscaling = tileGrid.getResolution(tileCoord[0]) / sourceTileResolution;
resolution = tilePixelRatio * upscaling;
} else {
tileSpaceCoordinate = coordinate;
}
replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString()); replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString());
found = found || replayGroup.forEachFeatureAtCoordinate( found = found || replayGroup.forEachFeatureAtCoordinate(
tileSpaceCoordinate, resolution, rotation, hitTolerance, {}, coordinate, resolution, rotation, hitTolerance, {},
/** /**
* @param {ol.Feature|ol.render.Feature} feature Feature. * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result. * @return {?} Callback result.
@@ -323,43 +296,26 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
* @private * @private
*/ */
ol.renderer.canvas.VectorTileLayer.prototype.getReplayTransform_ = function(tile, frameState) { ol.renderer.canvas.VectorTileLayer.prototype.getReplayTransform_ = function(tile, frameState) {
if (tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) { var layer = this.getLayer();
var layer = this.getLayer(); var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
var source = /** @type {ol.source.VectorTile} */ (layer.getSource()); var tileGrid = source.getTileGrid();
var tileGrid = source.getTileGrid(); var tileCoord = tile.tileCoord;
var tileCoord = tile.tileCoord; var tileResolution = tileGrid.getResolution(tileCoord[0]);
var tileResolution = var viewState = frameState.viewState;
tileGrid.getResolution(tileCoord[0]) / this.getTilePixelRatio_(source, tile); var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState; var renderResolution = viewState.resolution / pixelRatio;
var pixelRatio = frameState.pixelRatio; var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
var renderResolution = viewState.resolution / pixelRatio; var center = viewState.center;
var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent); var origin = ol.extent.getTopLeft(tileExtent);
var center = viewState.center; var size = frameState.size;
var origin = ol.extent.getTopLeft(tileExtent); var offsetX = Math.round(pixelRatio * size[0] / 2);
var size = frameState.size; var offsetY = Math.round(pixelRatio * size[1] / 2);
var offsetX = Math.round(pixelRatio * size[0] / 2); return ol.transform.compose(this.tmpTransform_,
var offsetY = Math.round(pixelRatio * size[1] / 2); offsetX, offsetY,
return ol.transform.compose(this.tmpTransform_, tileResolution / renderResolution, tileResolution / renderResolution,
offsetX, offsetY, viewState.rotation,
tileResolution / renderResolution, tileResolution / renderResolution, (origin[0] - center[0]) / tileResolution,
viewState.rotation, (center[1] - origin[1]) / tileResolution);
(origin[0] - center[0]) / tileResolution,
(center[1] - origin[1]) / tileResolution);
} else {
return this.getTransform(frameState, 0);
}
};
/**
* @private
* @param {ol.source.VectorTile} source Source.
* @param {ol.VectorTile} tile Tile.
* @return {number} The tile's pixel ratio.
*/
ol.renderer.canvas.VectorTileLayer.prototype.getTilePixelRatio_ = function(source, tile) {
return ol.extent.getWidth(tile.getExtent()) /
ol.size.toSize(source.getTileGrid().getTileSize(tile.tileCoord[0]))[0];
}; };
@@ -387,7 +343,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra
var offsetX = Math.round(pixelRatio * size[0] / 2); var offsetX = Math.round(pixelRatio * size[0] / 2);
var offsetY = Math.round(pixelRatio * size[1] / 2); var offsetY = Math.round(pixelRatio * size[1] / 2);
var tiles = this.renderedTiles; var tiles = this.renderedTiles;
var sourceTileGrid = source.getTileGrid();
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection); var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
var clips = []; var clips = [];
var zs = []; var zs = [];
@@ -404,15 +359,12 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra
if (sourceTile.getState() == ol.TileState.ERROR) { if (sourceTile.getState() == ol.TileState.ERROR) {
continue; continue;
} }
var tilePixelRatio = this.getTilePixelRatio_(source, sourceTile);
var replayGroup = sourceTile.getReplayGroup(layer, tileCoord.toString()); var replayGroup = sourceTile.getReplayGroup(layer, tileCoord.toString());
if (renderMode != ol.layer.VectorTileRenderType.VECTOR && !replayGroup.hasReplays(replays)) { if (renderMode != ol.layer.VectorTileRenderType.VECTOR && !replayGroup.hasReplays(replays)) {
continue; continue;
} }
var currentZ = sourceTile.tileCoord[0]; var currentZ = sourceTile.tileCoord[0];
var sourceResolution = sourceTileGrid.getResolution(currentZ); var transform = this.getTransform(frameState, worldOffset);
var transform = this.getReplayTransform_(sourceTile, frameState);
ol.transform.translate(transform, worldOffset * tilePixelRatio / sourceResolution, 0);
var currentClip = replayGroup.getClipCoords(transform); var currentClip = replayGroup.getClipCoords(transform);
context.save(); context.save();
context.globalAlpha = layerState.opacity; context.globalAlpha = layerState.opacity;
@@ -492,7 +444,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function(
var z = tileCoord[0]; var z = tileCoord[0];
var pixelRatio = frameState.pixelRatio; var pixelRatio = frameState.pixelRatio;
var source = /** @type {ol.source.VectorTile} */ (layer.getSource()); var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
var sourceTileGrid = source.getTileGrid();
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection); var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
var resolution = tileGrid.getResolution(z); var resolution = tileGrid.getResolution(z);
var context = tile.getContext(layer); var context = tile.getContext(layer);
@@ -505,22 +456,10 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function(
if (sourceTile.getState() == ol.TileState.ERROR) { if (sourceTile.getState() == ol.TileState.ERROR) {
continue; continue;
} }
var tilePixelRatio = this.getTilePixelRatio_(source, sourceTile);
var sourceTileCoord = sourceTile.tileCoord;
var pixelScale = pixelRatio / resolution; var pixelScale = pixelRatio / resolution;
var transform = ol.transform.reset(this.tmpTransform_); var transform = ol.transform.reset(this.tmpTransform_);
if (sourceTile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) { ol.transform.scale(transform, pixelScale, -pixelScale);
var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord, this.tmpExtent); ol.transform.translate(transform, -tileExtent[0], -tileExtent[3]);
var sourceResolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
var renderPixelRatio = pixelRatio / tilePixelRatio * sourceResolution / resolution;
ol.transform.scale(transform, renderPixelRatio, renderPixelRatio);
var offsetX = (sourceTileExtent[0] - tileExtent[0]) / sourceResolution * tilePixelRatio;
var offsetY = (tileExtent[3] - sourceTileExtent[3]) / sourceResolution * tilePixelRatio;
ol.transform.translate(transform, Math.round(offsetX), Math.round(offsetY));
} else {
ol.transform.scale(transform, pixelScale, -pixelScale);
ol.transform.translate(transform, -tileExtent[0], -tileExtent[3]);
}
var replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString()); var replayGroup = sourceTile.getReplayGroup(layer, tile.tileCoord.toString());
replayGroup.replay(context, pixelRatio, transform, 0, {}, replays, true); replayGroup.replay(context, pixelRatio, transform, 0, {}, replays, true);
} }
-4
View File
@@ -86,10 +86,6 @@ ol.source.VectorTile = function(options) {
*/ */
this.tileGrids_ = {}; this.tileGrids_ = {};
if (!this.tileGrid) {
this.tileGrid = this.getTileGridForProjection(ol.proj.get(options.projection || 'EPSG:3857'));
}
}; };
ol.inherits(ol.source.VectorTile, ol.source.UrlTile); ol.inherits(ol.source.VectorTile, ol.source.UrlTile);
@@ -13,6 +13,7 @@ goog.require('ol.geom.Point');
goog.require('ol.layer.VectorTile'); goog.require('ol.layer.VectorTile');
goog.require('ol.proj'); goog.require('ol.proj');
goog.require('ol.proj.Projection'); goog.require('ol.proj.Projection');
goog.require('ol.render.Feature');
goog.require('ol.renderer.canvas.VectorTileLayer'); goog.require('ol.renderer.canvas.VectorTileLayer');
goog.require('ol.source.VectorTile'); goog.require('ol.source.VectorTile');
goog.require('ol.style.Style'); goog.require('ol.style.Style');
@@ -24,7 +25,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
describe('constructor', function() { describe('constructor', function() {
var map, layer, source, feature1, feature2, target, tileCallback; var map, layer, source, feature1, feature2, feature3, target, tileCallback;
beforeEach(function() { beforeEach(function() {
tileCallback = function() {}; tileCallback = function() {};
@@ -51,11 +52,12 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
})]; })];
feature1 = new ol.Feature(new ol.geom.Point([1, -1])); feature1 = new ol.Feature(new ol.geom.Point([1, -1]));
feature2 = new ol.Feature(new ol.geom.Point([0, 0])); feature2 = new ol.Feature(new ol.geom.Point([0, 0]));
feature3 = new ol.render.Feature('Point', [1, -1], []);
feature2.setStyle(featureStyle); feature2.setStyle(featureStyle);
var TileClass = function() { var TileClass = function() {
ol.VectorTile.apply(this, arguments); ol.VectorTile.apply(this, arguments);
this.setState('loaded'); this.setState('loaded');
this.setFeatures([feature1, feature2]); this.setFeatures([feature1, feature2, feature3]);
this.setProjection(ol.proj.get('EPSG:4326')); this.setProjection(ol.proj.get('EPSG:4326'));
tileCallback(this); tileCallback(this);
}; };
@@ -106,7 +108,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
it('does not render replays for pure image rendering', function() { it('does not render replays for pure image rendering', function() {
layer.renderMode_ = 'image'; layer.renderMode_ = 'image';
var spy = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype, var spy = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'getReplayTransform_'); 'getTransform');
map.renderSync(); map.renderSync();
expect(spy.callCount).to.be(0); expect(spy.callCount).to.be(0);
spy.restore(); spy.restore();
@@ -114,7 +116,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
it('renders both replays and images for hybrid rendering', function() { it('renders both replays and images for hybrid rendering', function() {
var spy1 = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype, var spy1 = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'getReplayTransform_'); 'getTransform');
var spy2 = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype, var spy2 = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'renderTileImage_'); 'renderTileImage_');
map.renderSync(); map.renderSync();
@@ -130,7 +132,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
renderer: function() {} renderer: function() {}
})); }));
var spy = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype, var spy = sinon.spy(ol.renderer.canvas.VectorTileLayer.prototype,
'getReplayTransform_'); 'getTransform');
map.renderSync(); map.renderSync();
expect(spy.callCount).to.be(1); expect(spy.callCount).to.be(1);
spy.restore(); spy.restore();
@@ -142,6 +144,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
map.renderSync(); map.renderSync();
expect(spy.getCall(0).args[2]).to.be(layer.getStyle()); expect(spy.getCall(0).args[2]).to.be(layer.getStyle());
expect(spy.getCall(1).args[2]).to.be(feature2.getStyle()); expect(spy.getCall(1).args[2]).to.be(feature2.getStyle());
spy.restore();
}); });
it('transforms geometries when tile and view projection are different', function() { it('transforms geometries when tile and view projection are different', function() {
@@ -155,16 +158,17 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
ol.proj.fromLonLat([1, -1])); ol.proj.fromLonLat([1, -1]));
}); });
it('leaves geometries untouched when units are tile-pixels', function() { it('Geometries are transformed from tile-pixels', function() {
var proj = new ol.proj.Projection({code: '', units: 'tile-pixels'}); var proj = new ol.proj.Projection({code: 'EPSG:3857', units: 'tile-pixels'});
var tile; var tile;
tileCallback = function(t) { tileCallback = function(t) {
t.setProjection(proj); t.setProjection(proj);
tile = t; tile = t;
}; };
map.renderSync(); map.renderSync();
expect(tile.getProjection()).to.equal(proj); expect(tile.getProjection()).to.equal(ol.proj.get('EPSG:3857'));
expect(feature1.getGeometry().getCoordinates()).to.eql([1, -1]); expect(feature1.getGeometry().getCoordinates()).to.eql([-20027724.40316874, 20047292.282409746]);
expect(feature3.flatCoordinates_).to.eql([-20027724.40316874, 20047292.282409746]);
}); });
it('works for multiple layers that use the same source', function() { it('works for multiple layers that use the same source', function() {
@@ -189,14 +193,6 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
spy2.restore(); spy2.restore();
}); });
it('uses the extent of the source tile', function() {
var renderer = map.getRenderer().getLayerRenderer(layer);
var tile = new ol.VectorTile([0, 0, 0], 2);
tile.setExtent([0, 0, 4096, 4096]);
var tilePixelRatio = renderer.getTilePixelRatio_(source, tile);
expect(tilePixelRatio).to.be(16);
});
}); });
describe('#prepareFrame', function() { describe('#prepareFrame', function() {