1. A concise explanation of the problem you’re experiencing.
I am currently using a custom Mapbox Vector Tile implementation within Cesium. This implementation uses a MVT ImageryProvider with the Protobuf data being styled and then generated on a canvas using OpenLayers’ Canvas ReplayGroup.
As you know, Ceisum’s 3D viewer requires multiple imagery LODs to display a scene. The multiple LODs lead to label display issues, as shown below.
2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.
Here is my custom MVT ImageryProvider code that uses OL to render city labels, boundaries and other features.
MapboxVectorTile.prototype.requestImage = function(x, y, level, request) {
var cacheTile = findTileInQueue(x, y, level, this._tileQueue);
if(!defined(cacheTile)) {
var that = this;
var url = this._url;
var index = (x + y + level) % this._subdomains.length;
url = url.replace(’{x}’, x).replace(’{y}’, y).replace(’{z}’, level).replace(’{k}’, this._key).replace(’{s}’, this._subdomains[index]);
return Resource.fetchArrayBuffer(url).then(function(arrayBuffer) {
var canvas = document.createElement(‘canvas’);
canvas.width = that._tileWidth;
canvas.height = that._tileHeight;
var vectorContext = canvas.getContext(‘2d’);
var features = that._mvtParser.readFeatures(arrayBuffer);
var styleFun = that._styleFun();
var extent = [0, 0, 4096, 4096];
var _replayGroup = new that._ol.render.canvas.ReplayGroup(0, extent, 8, true, 100);
for(var i = 0; i < features.length; i++){
var feature = features[i];
var styles = styleFun(features[i], that._resolutions[level]);
for(var j=0;j<styles.length;j++)
{
that.ol.renderer.vector.renderFeature(_replayGroup, feature, styles[j], 16);
}
}
_replayGroup.finish();
_replayGroup.replay(vectorContext, that._pixelRatio, that._transform, 0, {}, that._replays, true);
if(that._tileQueue.count > that._cacheSize){
trimTiles(that._tileQueue, that._cacheSize / 2);
}
canvas.xMvt = x;
canvas.yMvt = y;
canvas.zMvt = level;
that._tileQueue.markTileRendered(canvas);
_replayGroup = null;
return canvas;
});
}
return cacheTile;
};
``
Here’s the “styleFunction.”
styleFunction: function() {
var fill = new ol.style.Fill({color: ‘’});
var stroke = new ol.style.Stroke({color: ‘’, width: 1});
var polygon = new ol.style.Style({fill: fill});
var strokedPolygon = new ol.style.Style({fill: fill, stroke: stroke});
var line = new ol.style.Style({stroke: stroke});
var text = new ol.style.Style({text: new ol.style.Text({
text: ‘’,
fill: fill,
stroke: stroke
})});
var styles = ;
return function(feature, resolution) {
var length = 0;
var layer = feature.get(‘layer’);
if (layer != ‘transportation’ && layer != ‘transportation_name’) {
return ;
}
var cls = feature.get(‘class’);
var type = feature.get(‘type’);
var scalerank = feature.get(‘scalerank’);
var labelrank = feature.get(‘labelrank’);
var adminLevel = feature.get(‘admin_level’);
var maritime = feature.get(‘maritime’);
var disputed = feature.get(‘disputed’);
var maki = feature.get(‘maki’);
var geom = feature.getGeometry().getType();
var interstate_color = Colors.hexToRgb(that.app.preferences.interstate_color);
interstate_color[3] = that.app.preferences.interstate_opacity;
if (layer == ‘transportation’ && cls == ‘motorway_link’) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘service’) {
stroke.setColor(’#cfcdca’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ &&
(cls == ‘street’ || cls == ‘street_limited’)) {
stroke.setColor(’#cfcdca’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘main’ &&
resolution <= 1222.99245256282) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘motorway’) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘path’) {
stroke.setColor(’#cba’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘major_rail’) {
stroke.setColor(’#bbb’);
stroke.setWidth(2);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘motorway_link’) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && (cls == ‘street’ ||
cls == ‘street_limited’) && geom == ‘LineString’) {
stroke.setColor(’#cfcdca’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘main’ &&
resolution <= 1222.99245256282) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘motorway’ &&
resolution <= 4891.96981025128) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘path’) {
stroke.setColor(’#cba’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘major_rail’) {
stroke.setColor(’#bbb’);
stroke.setWidth(2);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘motorway_link’) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘motorway’) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘service’) {
stroke.setColor(’#cfcdca’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ &&
(cls == ‘street’ || cls == ‘street_limited’)) {
stroke.setColor(’#cfcdca’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘main’ &&
resolution <= 1222.99245256282) {
stroke.setColor(interstate_color);
stroke.setWidth(that.app.preferences.interstate_width);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘path’) {
stroke.setColor(’#cba’);
stroke.setWidth(1);
styles[length++] = line;
} else if (layer == ‘transportation’ && cls == ‘major_rail’) {
stroke.setColor(’#bbb’);
stroke.setWidth(2);
styles[length++] = line;
}
styles.length = length;
return styles;
};
},
``
3. Context. Why do you need to do this? We might know a better way to accomplish your goal.
I previously used a GeoJSON file for cities. This produced the most aesthetically-pleasing city labels because there wasn’t any jagged/cut-off text and it gave the added benefit of Earth-tangent city labels for roll != 0.0.
My Protobuf MVT output contains much more information and is tiled, reducing the bandwidth necessary to render multiple features (city labels, state boundaries, county boundaries, roads, etc. etc.)
I’m looking for ANY advice on how to improve this without returning to a GeoJSON city database. Is it possible to render the MVTs using a single zoom level instead of compositing multiple zoom levels, which****always leads to broken text?
4. The Cesium version you’re using, your operating system and browser.
Latest master/trunk.