changed point renderer

This commit is contained in:
javi 2013-08-28 12:38:48 +02:00
parent d4cf6b0f0e
commit 9ff42f5d4d
2 changed files with 107 additions and 48 deletions

View File

@ -28,7 +28,6 @@
this._canvas = canvas; this._canvas = canvas;
this._ctx = canvas.getContext('2d'); this._ctx = canvas.getContext('2d');
this._sprites = {}; this._sprites = {};
this._trailsSprites = [];
this._shader = null; this._shader = null;
this._trailsShader = null; this._trailsShader = null;
//carto.tree.Reference.set(torque['torque-reference']); //carto.tree.Reference.set(torque['torque-reference']);
@ -48,22 +47,7 @@
setCartoCSS: function(cartocss) { setCartoCSS: function(cartocss) {
// clean sprites // clean sprites
this._sprites = {}; this._sprites = {};
this._trailsSprites = [];
this._cartoCssStyle = new carto.RendererJS().render(cartocss); this._cartoCssStyle = new carto.RendererJS().render(cartocss);
if(this._cartoCssStyle.getLayers().length < 1) {
throw new Error("CartoCSS must have at least one layer");
}
this._shader = this._cartoCssStyle.getDefault();
if(!this._shader) {
throw new Error("there is not default layer in CartoCSS");
}
this._trailsShader = this._cartoCssStyle.findLayer({ attachment: 'trails' });
if(this._trailsShader) {
var st = this._trailsShader.getStyle('canvas-2d', { value: 0}, {zoom: 1});
this._trailSteps = +st['trail-steps'];
}
}, },
// //
@ -94,11 +78,13 @@
}, },
renderTile: function(tile, key) { renderTile: function(tile, key) {
this._renderTile(tile, key, this._sprites, this._shader); var layers = this._cartoCssStyle.getLayers();
if(this._trailsShader) { for(var i = 0, n = layers.length; i < n; ++i ) {
for(var i = 0; i < this._trailSteps; ++i) { var layer = layers[i];
this._trailsSprites[i] = this._trailsSprites[i] || {}; for(var fr = 0; fr < layer.frames().length; ++fr) {
this._renderTile(tile, key - (i + 1), this._trailsSprites[i], this._trailsShader, { 'trail-step': i + 1 }); var frame = layer.frames()[fr];
var sprites = this._sprites[frame] || (this._sprites[frame] = []);
this._renderTile(tile, key - frame, frame, sprites, layer);
} }
} }
}, },
@ -107,9 +93,9 @@
// renders a tile in the canvas for key defined in // renders a tile in the canvas for key defined in
// the torque tile // the torque tile
// //
_renderTile: function(tile, key, sprites, shader, shaderVars) { _renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars) {
if(!this._canvas) return; if(!this._canvas) return;
//var prof = Profiler.get('render').start(); var prof = Profiler.metric('PointRenderer:renderTile').start();
var ctx = this._ctx; var ctx = this._ctx;
var res = this.options.resolution; var res = this.options.resolution;
var activePixels = tile.timeCount[key]; var activePixels = tile.timeCount[key];
@ -124,7 +110,7 @@
if(c) { if(c) {
var sp = sprites[c]; var sp = sprites[c];
if(!sp) { if(!sp) {
sp = sprites[c] = this.generateSprite(shader, c, _.extend({ zoom: tile.zoom }, shaderVars)); sp = sprites[c] = this.generateSprite(shader, c, _.extend({ zoom: tile.zoom, 'frame-offset': frame_offset }, shaderVars));
} }
var x = tile.x[posIdx]*res - (sp.width >> 1); var x = tile.x[posIdx]*res - (sp.width >> 1);
var y = (256 - res - res*tile.y[posIdx]) - (sp.height >> 1); var y = (256 - res - res*tile.y[posIdx]) - (sp.height >> 1);
@ -132,7 +118,7 @@
} }
} }
} }
//prof.end(); prof.end();
} }
}; };

119
vendor/carto.js vendored
View File

@ -1866,6 +1866,9 @@ function require(arg) {
if(!mod) { if(!mod) {
mod = window.carto[arg] mod = window.carto[arg]
} }
if(!mod) {
mod = window[arg.split('/')[1]];
}
// try global scope // try global scope
if(!mod) { if(!mod) {
mod = window[arg] mod = window[arg]
@ -1874,7 +1877,7 @@ function require(arg) {
} }
var carto, tree, _; var carto, tree, _;
if (typeof(process) !== 'undefined') { if (typeof(exports) !== 'undefined') {
carto = exports; carto = exports;
tree = require('./tree'); tree = require('./tree');
_ = require('underscore'); _ = require('underscore');
@ -2175,9 +2178,6 @@ carto.Parser = function Parser(env) {
// and sorted according to specificitySort // and sorted according to specificitySort
root.toList = (function() { root.toList = (function() {
var line, lines, column; var line, lines, column;
if (!(window && window._)) {
var _ = require('underscore')._;
}
return function(env) { return function(env) {
env.error = function(e) { env.error = function(e) {
if (!env.errors) env.errors = new Error(''); if (!env.errors) env.errors = new Error('');
@ -2501,11 +2501,13 @@ carto.Parser = function Parser(env) {
var e, elements = []; var e, elements = [];
var f, filters = new tree.Filterset(); var f, filters = new tree.Filterset();
var z, zoom = tree.Zoom.all; var z, zoom = tree.Zoom.all;
var fo, frame_offset = tree.FrameOffset.null;
var segments = 0, conditions = 0; var segments = 0, conditions = 0;
while ( while (
(e = $(this.element)) || (e = $(this.element)) ||
(z = $(this.zoom)) || (z = $(this.zoom)) ||
(fo = $(this.frame_offset)) ||
(f = $(this.filter)) || (f = $(this.filter)) ||
(a = $(this.attachment)) (a = $(this.attachment))
) { ) {
@ -2515,6 +2517,9 @@ carto.Parser = function Parser(env) {
} else if (z) { } else if (z) {
zoom &= z; zoom &= z;
conditions++; conditions++;
} else if (fo) {
frame_offset = fo;
conditions++;
} else if (f) { } else if (f) {
filters.add(f); filters.add(f);
conditions++; conditions++;
@ -2532,7 +2537,7 @@ carto.Parser = function Parser(env) {
} }
if (segments) { if (segments) {
return new tree.Selector(filters, zoom, elements, attachment, conditions, memo); return new tree.Selector(filters, zoom, frame_offset, elements, attachment, conditions, memo);
} }
}, },
@ -2549,6 +2554,17 @@ carto.Parser = function Parser(env) {
} }
}, },
frame_offset: function() {
save();
var op, val;
if ($(/^\[\s*frame-offset/g) &&
(op = $(this.entities.comparison)) &&
(val = $(/^\d+/)) &&
$(']')) {
return tree.FrameOffset(op, val, memo);
}
},
zoom: function() { zoom: function() {
save(); save();
var op, val; var op, val;
@ -2957,6 +2973,7 @@ tree.Definition = function Definition(selector, rules) {
} }
this.filters = selector.filters; this.filters = selector.filters;
this.zoom = selector.zoom; this.zoom = selector.zoom;
this.frame_offset = selector.frame_offset;
this.attachment = selector.attachment || '__default__'; this.attachment = selector.attachment || '__default__';
this.specificity = selector.specificity(); this.specificity = selector.specificity();
}; };
@ -3614,6 +3631,33 @@ tree.FontSet.prototype.toXML = function(env) {
}; };
})(require('../tree')); })(require('../tree'));
var tree = require('../tree');
// Storage for Frame offset value
// and stores them as bit-sequences so that they can be combined,
// inverted, and compared quickly.
tree.FrameOffset = function(op, value, index) {
value = parseInt(value, 10);
if (value > tree.FrameOffset.max || value <= 0) {
throw {
message: 'Only frame-offset levels between 1 and ' +
tree.FrameOffset.max + ' supported.',
index: index
};
}
if (op !== '=') {
throw {
message: 'only = operator is supported for frame-offset',
index: index
};
}
return value;
};
tree.FrameOffset.max = 32;
tree.FrameOffset.null = 0;
(function(tree) { (function(tree) {
// //
// RGB Colors - #ff0014, #eee // RGB Colors - #ff0014, #eee
@ -4215,7 +4259,7 @@ tree.Ruleset.prototype = {
if (match = selector.match(rule.selectors[j])) { if (match = selector.match(rule.selectors[j])) {
if (selector.elements.length > 1) { if (selector.elements.length > 1) {
Array.prototype.push.apply(rules, rule.find( Array.prototype.push.apply(rules, rule.find(
new tree.Selector(null, null, selector.elements.slice(1)), self)); new tree.Selector(null, null, null, selector.elements.slice(1)), self));
} else { } else {
rules.push(rule); rules.push(rule);
} }
@ -4247,6 +4291,7 @@ tree.Ruleset.prototype = {
// filters. This means that we only have to clone when // filters. This means that we only have to clone when
// the zoom levels or the attachment is different too. // the zoom levels or the attachment is different too.
if (parent.zoom === (parent.zoom & child.zoom) && if (parent.zoom === (parent.zoom & child.zoom) &&
parent.frame_offset === child.frame_offset &&
parent.attachment === child.attachment) { parent.attachment === child.attachment) {
continue; continue;
} else { } else {
@ -4261,6 +4306,7 @@ tree.Ruleset.prototype = {
var clone = Object.create(tree.Selector.prototype); var clone = Object.create(tree.Selector.prototype);
clone.filters = mergedFilters; clone.filters = mergedFilters;
clone.zoom = parent.zoom & child.zoom; clone.zoom = parent.zoom & child.zoom;
clone.frame_offset = child.frame_offset;
clone.elements = parent.elements.concat(child.elements); clone.elements = parent.elements.concat(child.elements);
if (parent.attachment && child.attachment) { if (parent.attachment && child.attachment) {
clone.attachment = parent.attachment + '/' + child.attachment; clone.attachment = parent.attachment + '/' + child.attachment;
@ -4307,10 +4353,11 @@ var assert = require('assert');
(function(tree) { (function(tree) {
tree.Selector = function Selector(filters, zoom, elements, attachment, conditions, index) { tree.Selector = function Selector(filters, zoom, frame_offset, elements, attachment, conditions, index) {
this.elements = elements || []; this.elements = elements || [];
this.attachment = attachment; this.attachment = attachment;
this.filters = filters || {}; this.filters = filters || {};
this.frame_offset = frame_offset;
this.zoom = typeof zoom !== 'undefined' ? zoom : tree.Zoom.all; this.zoom = typeof zoom !== 'undefined' ? zoom : tree.Zoom.all;
this.conditions = conditions; this.conditions = conditions;
this.index = index; this.index = index;
@ -4749,8 +4796,9 @@ function clamp(val) {
} }
})(require('./tree')); })(require('./tree'));
(function() { (function(carto) {
var tree = require('../tree'); var tree = require('./tree');
var _ = require('underscore');
// monkey patch less classes // monkey patch less classes
tree.Value.prototype.toJS = function() { tree.Value.prototype.toJS = function() {
@ -4794,12 +4842,12 @@ tree.Definition.prototype.toJS = function() {
// merge conditions from filters with zoom condition of the // merge conditions from filters with zoom condition of the
// definition // definition
var zoom = "(" + this.zoom + " & (1 << ctx.zoom))"; var zoom = "(" + this.zoom + " & (1 << ctx.zoom))";
var _if = this.filters.toJS() var frame_offset = this.frame_offset;
if(_if && _if.length > 0) { var _if = this.filters.toJS();
_if += " && " + zoom; var filters = [zoom];
} else { if(_if) filters.push(_if);
_if = zoom; if(frame_offset) filters.push('ctx["frame-offset"] === ' + frame_offset);
} _if = filters.join(" && ");
_.each(this.rules, function(rule) { _.each(this.rules, function(rule) {
if(rule instanceof tree.Rule) { if(rule instanceof tree.Rule) {
shaderAttrs[rule.name] = shaderAttrs[rule.name] || []; shaderAttrs[rule.name] = shaderAttrs[rule.name] || [];
@ -4826,7 +4874,8 @@ tree.Definition.prototype.toJS = function() {
}; };
function CartoCSS(style) { function CartoCSS(style, options) {
this.options = options || {};
if(style) { if(style) {
this.setStyle(style); this.setStyle(style);
} }
@ -4912,7 +4961,7 @@ CartoCSS.renderers['canvas-2d'] = {
} }
var renderer = CartoCSS.renderers['svg']; var renderer = CartoCSS.renderers['svg'];
var ref = window.carto['mapnik-reference'].version.latest; var ref = require('mapnik-reference').version.latest;
var to_load = ['polygon', 'line', 'point', 'markers']; var to_load = ['polygon', 'line', 'point', 'markers'];
for(var ss in to_load) { for(var ss in to_load) {
var s = to_load[ss]; var s = to_load[ss];
@ -4932,6 +4981,11 @@ CartoCSS.Layer.prototype = {
return this.fullName().split('::')[0]; return this.fullName().split('::')[0];
}, },
// frames this layer need to be rendered
frames: function() {
return this.shader.frames;
},
attachment: function() { attachment: function() {
return this.fullName().split('::')[1]; return this.fullName().split('::')[1];
}, },
@ -4945,7 +4999,7 @@ CartoCSS.Layer.prototype = {
getStyle: function(target, props, context) { getStyle: function(target, props, context) {
var style = {}; var style = {};
for(var i in this.shader) { for(var i in this.shader) {
if(i !== 'attachment') { if(i !== 'attachment' && i !== 'zoom' && i !== 'frames') {
style[i] = this.shader[i](props, context); style[i] = this.shader[i](props, context);
} }
} }
@ -5017,7 +5071,7 @@ CartoCSS.prototype = {
_createFn: function(ops) { _createFn: function(ops) {
var body = ops.join('\n'); var body = ops.join('\n');
console.log(body); if(this.options.debug) console.log(body);
return Function("data","ctx", "var _value = null; " + body + "; return _value; "); return Function("data","ctx", "var _value = null; " + body + "; return _value; ");
}, },
@ -5048,6 +5102,7 @@ CartoCSS.prototype = {
try { try {
ruleset = (new carto.Parser(parse_env)).parse(cartocss); ruleset = (new carto.Parser(parse_env)).parse(cartocss);
} catch(e) { } catch(e) {
console.log(e.stack);
// add the style.mss string to match the response from the server // add the style.mss string to match the response from the server
parse_env.errors.push(e.message); parse_env.errors.push(e.message);
return; return;
@ -5061,6 +5116,8 @@ CartoCSS.prototype = {
var def = defs[i]; var def = defs[i];
var key = def.elements[0] + "::" + def.attachment; var key = def.elements[0] + "::" + def.attachment;
var layer = layers[key] = (layers[key] || {}); var layer = layers[key] = (layers[key] || {});
layer.frames = [];
layer.zoom = tree.Zoom.all;
var props = def.toJS(); var props = def.toJS();
for(var v in props) { for(var v in props) {
(layer[v] = (layer[v] || [])).push(props[v].join('\n')) (layer[v] = (layer[v] || [])).push(props[v].join('\n'))
@ -5073,15 +5130,26 @@ CartoCSS.prototype = {
for(var i = 0; i < defs.length; ++i) { for(var i = 0; i < defs.length; ++i) {
var def = defs[i]; var def = defs[i];
var k = def.elements[0] + "::" + def.attachment; var k = def.elements[0] + "::" + def.attachment;
var layer = layers[k];
if(!done[k]) { if(!done[k]) {
var layer = layers[k];
for(var prop in layer) { for(var prop in layer) {
layer[prop] = this._createFn(layer[prop]); if (prop !== 'zoom' && prop !== 'frames') {
if(this.options.debug) console.log("****", prop);
layer[prop] = this._createFn(layer[prop]);
}
} }
layer.attachment = k; layer.attachment = k;
ordered_layers.push(layer); ordered_layers.push(layer);
done[k] = true; done[k] = true;
} }
layer.zoom |= def.zoom;
layer.frames.push(def.frame_offset);
}
// uniq the frames
for(i = 0; i < ordered_layers.length; ++i) {
ordered_layers[i].frames = _.uniq(ordered_layers[i].frames);
} }
return ordered_layers; return ordered_layers;
@ -5091,6 +5159,7 @@ CartoCSS.prototype = {
} }
}; };
carto.RendererJS = function (options) { carto.RendererJS = function (options) {
this.options = options || {}; this.options = options || {};
this.options.mapnik_version = this.options.mapnik_version || 'latest'; this.options.mapnik_version = this.options.mapnik_version || 'latest';
@ -5099,7 +5168,11 @@ carto.RendererJS = function (options) {
// Prepare a javascript object which contains the layers // Prepare a javascript object which contains the layers
carto.RendererJS.prototype.render = function render(cartocss, callback) { carto.RendererJS.prototype.render = function render(cartocss, callback) {
tree.Reference.setVersion(this.options.mapnik_version); tree.Reference.setVersion(this.options.mapnik_version);
return new CartoCSS(cartocss); return new CartoCSS(cartocss, this.options);
}
if(typeof(module) !== 'undefined') {
module.exports = carto.RendererJS;
} }
})();
})(require('../carto'));