restores point renderer

This commit is contained in:
Francisco Dans 2015-08-20 13:33:25 +02:00
parent 1b0f79b92f
commit 9ad0ce8582

View File

@ -3,9 +3,6 @@ var cartocss = require('./cartocss_render');
var Profiler = require('../profiler');
var carto = global.carto || require('carto');
var Filters = require('./torque_filters');
var d3 = require('d3');
var contour = require('./contour');
var cSpline = require('cardinal-spline');
var TAU = Math.PI * 2;
var DEFAULT_CARTOCSS = [
@ -62,7 +59,6 @@ var cSpline = require('cardinal-spline');
this._gradients = {};
this._forcePoints = false;
this.globalGrid = [];
}
torque.extend(PointRenderer.prototype, torque.Event, {
@ -109,10 +105,74 @@ var cSpline = require('cardinal-spline');
this._sprites = [];
},
//
// generate sprite based on cartocss style
//
generateSprite: function(shader, value, shaderVars) {
var self = this;
var prof = Profiler.metric('torque.renderer.point.generateSprite').start();
var st = shader.getStyle({
value: value
}, shaderVars);
if(this._style === null || this._style !== st){
this._style = st;
}
var pointSize = st['marker-width'];
if (!pointSize) {
return null;
}
if (st['marker-opacity'] === 0 && !st['marker-line-opacity']) {
return null;
}
var canvas = this._createCanvas();
var ctx = canvas.getContext('2d');
var markerFile = st["marker-file"] || st["point-file"];
var qualifiedUrl = markerFile && this._qualifyURL(markerFile);
if (qualifiedUrl && this._iconsToLoad <= 0 && this._icons[qualifiedUrl]) {
var img = this._icons[qualifiedUrl];
var dWidth = Math.min(st['marker-width'] * 2 || img.width, cartocss.MAX_SPRITE_RADIUS * 2);
var dHeight = Math.min((st['marker-height'] || dWidth) * (img.width / img.height), cartocss.MAX_SPRITE_RADIUS * 2);
canvas.width = ctx.width = dWidth;
canvas.height = ctx.height = dHeight;
ctx.scale(dWidth/img.width, dHeight/img.height);
cartocss.renderSprite(ctx, img, st);
} else {
// take into account the exterior ring to calculate the size
var canvasSize = (st['marker-line-width'] || 0) + pointSize*2;
var w = ctx.width = canvas.width = ctx.height = canvas.height = Math.ceil(canvasSize);
ctx.translate(w/2, w/2);
var mt = st['marker-type'];
if (mt && mt === 'rectangle') {
cartocss.renderRectangle(ctx, st);
} else {
cartocss.renderPoint(ctx, st);
}
}
prof.end(true);
if (torque.flags.sprites_to_images) {
var i = this._createImage();
i.src = canvas.toDataURL();
return i;
}
return canvas;
},
//
// renders all the layers (and frames for each layer) from cartocss
//
renderTile: function(tile, key, pos) {
renderTile: function(tile, key, callback) {
if (this._iconsToLoad > 0) {
this.on('allIconsLoaded', function() {
this.renderTile.apply(this, [tile, key, callback]);
@ -129,12 +189,14 @@ var cSpline = require('cardinal-spline');
for(var fr = 0; fr < layer.frames().length; ++fr) {
var frame = layer.frames()[fr];
var fr_sprites = sprites[frame] || (sprites[frame] = []);
this._renderTile(tile, key - frame, frame, fr_sprites, layer, pos);
this._renderTile(tile, key - frame, frame, fr_sprites, layer);
}
}
}
prof.end(true);
return callback && callback(null);
},
_createCanvas: function() {
@ -178,7 +240,7 @@ var cSpline = require('cardinal-spline');
// renders a tile in the canvas for key defined in
// the torque tile
//
_renderTile: function(tile, key, frame_offset, sprites, shader, pos) {
_renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars) {
if (!this._canvas) return;
var prof = Profiler.metric('torque.renderer.point.renderTile').start();
@ -194,61 +256,27 @@ var cSpline = require('cardinal-spline');
var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1)
var activePixels = tile.timeCount[key];
var anchor = this.options.resolution/2;
/*
Torque Isolines
To be moved somewhere else (ideally something link isolines.js within /renderer/)
*/
var isolines = true;
if (isolines) {
this._gridData(tile);
}
prof.end(true);
},
_gridData: function(tile){
var valsPerTile = this.TILE_SIZE/this.options.resolution;
var difX = tile.coord.x - this.firstTileCoords.coord.x;
var difY = tile.coord.y - this.firstTileCoords.coord.y;
if (difX < 0 || difY < 0) return;
// baseIndex is the distance to the upper left corner of the grid, in cells
var baseIndex = {
x: (difX) * valsPerTile,
y: (difY) * valsPerTile
}
for(var i = 0; i < tile.renderData.length; i++){
var x = tile.x[i], y = tile.y[i];
this.globalGrid[baseIndex.y + (256 - y) / this.options.resolution -1][baseIndex.x + x/this.options.resolution] = tile.renderData[i];
}
},
_getPipe: function(cell, contour){
var parsedCell = cell.map(function(cornerValue){
if (cornerValue >= contour){
return "1";
if (activePixels) {
var pixelIndex = tile.timeIndex[key];
for(var p = 0; p < activePixels; ++p) {
var posIdx = tile.renderDataPos[pixelIndex + p];
var c = tile.renderData[pixelIndex + p];
if (c) {
var sp = sprites[c];
if (sp === undefined) {
sp = sprites[c] = this.generateSprite(shader, c, torque.extend({ zoom: tile.z, 'frame-offset': frame_offset }, shaderVars));
}
if (sp) {
var x = tile.x[posIdx]- (sp.width >> 1) + anchor;
var y = tileMax - tile.y[posIdx] + anchor; // flip mercator
ctx.drawImage(sp, x, y - (sp.height >> 1));
}
}
return "0";
}).join("");
var type = parseInt(parsedCell, 2);
var interpolated = true;
var N = interpolated? [this._lerp(cell[1], cell[0], contour), 0]: [0.5,0],
S = interpolated? [this._lerp(cell[2], cell[3], contour), 1]: [0.5,1],
E = interpolated? [1, this._lerp(cell[2], cell[1], contour)]: [1,0.5],
W = interpolated? [0, this._lerp(cell[3], cell[0], contour)]: [0,0.5]
if (type === 0 || type === 15) return null;
if (type === 1 || type === 14) return [W, S]
if (type === 2 || type === 13) return [S, E]
if (type === 3 || type === 12) return [W, E]
if (type === 4 || type === 11) return [N, E]
if (type === 6 || type === 9) return [N, S]
if (type === 7 || type === 8) return [W, N]
if (type === 5) return [W, N, S, E]
if (type === 10) return [W, S, N, E]
},
}
}
_lerp: function(valueA, valueB, contourValue){
return 1 + (-0.5) * (contourValue - valueA) / (valueB - valueA);
prof.end(true);
},
setBlendMode: function(b) {
@ -374,85 +402,44 @@ var cSpline = require('cardinal-spline');
}
},
drawIsolines: function(){
if (this.globalGrid.length > 0) {
var style = this._shader.getLayers()[1].getStyle({}, {zoom: 2});
var cellsY = this.globalGrid.length-1;
var contourValues = [0, 4, 8, 16, 32, 64, 128];
var ctx = this._ctx;
var res = this.options.resolution;
var startPos = this.firstTileCoords.pos;
ctx.strokeStyle = style["-isoline-line-color"] || "black";
ctx.lineWidth = style["-isoline-line-width"] || 2;
ctx.globalAlpha = style["-isoline-line-opacity"] || 0.8;
var grad = style["-isoline-line-ramp"] && this._generateGradient(style["-isoline-line-ramp"].args);
for (var c = 0; c < contourValues.length; c++) {
if(style["-isoline-line-decay"]){
var max = contourValues[contourValues.length - 1];
ctx.globalAlpha = (contourValues[c]/max)*(style["-isoline-line-opacity"] || 0.8);
}
if(grad){
ctx.strokeStyle = "rgb("+grad[4*contourValues[c]+1]+","+grad[4*contourValues[c]+2]+","+grad[4*contourValues[c]+3]+")";
}
for (var y = 0; y < cellsY; y++) {
for (var x = 0; x < this.globalGrid[y].length-1; x++){
var currentCell = [
this.globalGrid[y][x],
this.globalGrid[y][x+1],
this.globalGrid[y+1][x+1],
this.globalGrid[y+1][x]
];
var pipe = this._getPipe(currentCell, contourValues[c]);
if (pipe){
ctx.beginPath();
ctx.moveTo(res * (x + 0.5 + pipe[0][0]), res * (y + 0.5 + pipe[0][1]));
ctx.lineTo(res * (x + 0.5 + pipe[1][0]), res * (y + 0.5 + pipe[1][1]));
ctx.stroke();
if (pipe.length === 4){
ctx.beginPath();
ctx.moveTo(res * (x + 0.5 + pipe[2][0]), res * (y + 0.5 + pipe[2][1]));
ctx.lineTo(res * (x + 0.5 + pipe[3][0]), res * (y + 0.5 + pipe[3][1]));
ctx.stroke();
}
}
}
}
}
ctx.globalAlpha = 0;
}
},
_generateGradient: function(ramp){
var gradientCanvas = this._createCanvas(),
gctx = gradientCanvas.getContext('2d'),
gradient = gctx.createLinearGradient(0, 0, 0, 256);
gradientCanvas.width = 1;
gradientCanvas.height = 256;
for (var i = 0; i < ramp.length; i++) {
var color = "rgb("+ramp[i].rgb[0]+","+ramp[i].rgb[1]+","+ramp[i].rgb[2]+")";
gradient.addColorStop(i/(ramp.length-1), color);
}
gctx.fillStyle = gradient;
gctx.fillRect(0, 0, 1, 256);
return gctx.getImageData(0, 0, 1, 256).data;
},
applyFilters: function(){
this.drawIsolines();
// for (var y = 0; y < this.globalGrid.length; y++){
// for (var x = 0; x < this.globalGrid[0].length; x++){
// ctx.beginPath();
// ctx.arc(res/2 + x*res, res/2 + y*res, 1, 0, 2 * Math.PI, false);
// var value = this.globalGrid[y][x];
// ctx.fillStyle = "rgb("+0+", "+value * 50+", "+value * 50+")";
// if(value === 0) ctx.fillStyle = "red";
// ctx.fill();
// }
// }
}
if(this._style){
if(this._style['image-filters']){
function gradientKey(imf){
var hash = ""
for(var i = 0; i < imf.args.length; i++){
var rgb = imf.args[i].rgb;
hash += rgb[0] + ":" + rgb[1] + ":" + rgb[2];
}
return hash;
}
var gradient = this._gradients[gradientKey(this._style['image-filters'])];
if(!gradient){
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(r, g, b) {
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
gradient = {};
var colorize = this._style['image-filters'].args;
var increment = 1/colorize.length;
for (var i = 0; i < colorize.length; i++){
var key = increment * i + increment;
var rgb = colorize[i].rgb;
var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]);
gradient[key] = formattedColor;
}
this._gradients[gradientKey(this._style['image-filters'])] = gradient;
}
this._filters.gradient(gradient);
this._filters.draw();
}
}
}
});