From eaba6ee4dc8b00e5c8ac7203749749174627626a Mon Sep 17 00:00:00 2001 From: Stuart Lynn Date: Wed, 28 Oct 2015 18:48:22 -0400 Subject: [PATCH 1/4] adding filters to be able to filter by multiple conditions --- lib/torque/provider/tilejson.js | 35 ++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/torque/provider/tilejson.js b/lib/torque/provider/tilejson.js index d4b2af7a..3e6ff4e4 100644 --- a/lib/torque/provider/tilejson.js +++ b/lib/torque/provider/tilejson.js @@ -19,6 +19,7 @@ var tileJSON = function (options) { this._ready = false; this._tileQueue = []; + this._filters = {} this.options = options; this.options.coordinates_data_type = this.options.coordinates_data_type || Uint8Array; @@ -49,6 +50,13 @@ this.reload() }, + _setFilter:function(variable, start,end){ + this._filters[variable] = {type:'range', start:start,end:end) + this.reload(); + }, + _removefilter:function(variable){ + this._filters[variable] = undefined + }, /** * return the torque tile encoded in an efficient javascript * structure: @@ -60,16 +68,16 @@ */ createProccessTileWorker:function(){ var workerFunction = "var proccessTile ="+ this.proccessTileSerial.toString() - var wrapper = "; self.onmessage = function(e){var data = JSON.parse(e.data); JSON.stringify(self.postMessage(proccessTile(data.rows,data.coord, data.zoom, data.options)))}" + var wrapper = "; self.onmessage = function(e){var data = JSON.parse(e.data); JSON.stringify(self.postMessage(proccessTile(data.response,data.coord, data.zoom, data.options)))}" var script = workerFunction + wrapper; var blob = new Blob([script], {type: "text/javascript"}) var worker = new Worker(window.URL.createObjectURL(blob)) return worker }, - proccessTile:function(rows,coord,zoom,callback){ + proccessTile:function(response,coord,zoom,callback){ if(typeof(Worker) === "undefined"){ - callback(this.proccessTileSerial(rows,coord,zoom, this.options)) + callback(this.proccessTileSerial(response,coord,zoom, this.options)) } else{ var worker = this.createProccessTileWorker() @@ -79,20 +87,22 @@ } var workerSafeOptions= { - x : new this.options.coordinates_data_type(rows.length), - y : new this.options.coordinates_data_type(rows.length), cumulative: this.options.cumulative, valueDataType: this.options.valueDataType, resolution: this.options.resolution, } - worker.postMessage(JSON.stringify({rows: rows, coord: {x:coord.x,y:coord.y}, zoom:zoom, options: workerSafeOptions})) + worker.postMessage(JSON.stringify({response: response, coord: {x:coord.x,y:coord.y}, zoom:zoom, options: workerSafeOptions})) } }, - proccessTileSerial: function(rows, coord, zoom,options) { + proccessTileSerial: function(response, coord, zoom,options) { var r; - var x = options.x || new options.coordinates_data_type(rows.length); - var y = options.y || new options.coordinates_data_type(rows.length); + var data = JSON.parse(response) + var rows = data.pixels + var histograms = data.histograms + + var x = options.x || new Uint8Array(rows.length); + var y = options.y || new Uint8Array(rows.length); // count number of dates var dates = 0; @@ -189,7 +199,8 @@ timeIndex: timeIndex, renderDataPos: renderDataPos, renderData: renderData, - maxDate: maxDateSlots + maxDate: maxDateSlots, + histogram: histograms }; }, @@ -300,8 +311,8 @@ } torque.net.get( url , function (data) { if (data && data.responseText) { - var rows = JSON.parse(data.responseText); - self.proccessTile(rows.pixels, coord, zoom,callback.bind(self)); + + self.proccessTile(data.responseText, coord, zoom,callback.bind(self)); } else { callback(null); } From a8c1bf7682b5a47b0ff30e50373ca83e287eab5b Mon Sep 17 00:00:00 2001 From: Stuart Lynn Date: Wed, 28 Oct 2015 18:48:45 -0400 Subject: [PATCH 2/4] Code to aggregate histograms together --- lib/torque/leaflet/torque.js | 70 ++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/lib/torque/leaflet/torque.js b/lib/torque/leaflet/torque.js index 1c267194..d38f88d1 100644 --- a/lib/torque/leaflet/torque.js +++ b/lib/torque/leaflet/torque.js @@ -25,6 +25,8 @@ L.TorqueLayer = L.CanvasLayer.extend({ if (!torque.isBrowserSupported()) { throw new Error("browser is not supported by torque"); } + + this._histograms = [] options.tileLoader = true; this.key = 0; this.prevRenderedKey = 0; @@ -93,6 +95,10 @@ L.TorqueLayer = L.CanvasLayer.extend({ // don't load tiles that are not being shown if (t.zoom !== self._map.getZoom()) return; self._tileLoaded(t, tileData); + if(Object.keys(tileData.histogram).length > 0){ + self._addTileHistogram(t.x,t.y,t.zoom, tileData.histogram) + } + self._clearTileCaches(); if (tileData) { self.redraw(); @@ -102,7 +108,66 @@ L.TorqueLayer = L.CanvasLayer.extend({ }, this); }, + _invalidateHistograms:function(){ + this._histograms= undefined + }, + _addTileHistogram:function(x, y, zoom, histogram){ + + this._histograms[zoom] = this._histograms[zoom] ? this._histograms[zoom] : [] + this._histograms[zoom][x] = this._histograms[zoom][x] ? this._histograms[zoom][x] : [] + this._histograms[zoom][x][y] = histogram + this.fire('histogramAdded') + }, + histogramForVariable:function(variable){ + histogramParts=[] + Object.keys(this._tiles).forEach(function(t){ + var coord = t.split(":") + if(this._histograms[coord[2]][coord[0]][coord[1]]){ + histogramParts.push(this._histograms[coord[2]][coord[0]][coord[1]][variable]) + } + }.bind(this)) + return this._combineHistograms(histogramParts) + }, + _transfromHistogram:function(hist,zoom){ + var new_hist= { + bins: {}, + bounds: hist.bounds, + zoom : zoom, + x: 0 + } + var zoom_diff = zoom - hist.zoom; + new_hist.x = hist.x >> zoom_diff; + for( var k in hist.bins){ + var idx = (hist.x + k ) >> (zoom_diff - new_hist.x) + new_hist.bins[idx] = new_hist.bins[idx] || 0 + new_hist.bins[idx] += hist.bins[k] + } + return new_hist + }, + _combineHistograms:function(histograms){ + var minZoom = Math.min.apply(null,histograms.map(function(h){return h.zoom})) + var mappedHistograms = histograms.map(function(h){return this._transfromHistogram(h,minZoom)}.bind(this)) + + var combinedHistogram = { + bins:{}, + bounds: [ + Math.min.apply(null,mappedHistograms.map(function(h){return h.bounds[0]})), + Math.max.apply(null,mappedHistograms.map(function(h){return h.bounds[1]})) + ], + zoom: minZoom, + x: 0 + } + + mappedHistograms.forEach(function(histogram){ + Object.keys(histogram.bins).forEach(function(bin){ + combinedHistogram.bins[bin] = combinedHistogram.bins[bin] || 0 + combinedHistogram.bins[bin]+= histogram.bins[bin] + }) + }) + + return combinedHistogram + }, _clearTileCaches: function() { var t, tile; for(t in this._tiles) { @@ -332,6 +397,11 @@ L.TorqueLayer = L.CanvasLayer.extend({ return this.provider.getKeySpan(); }, + setQueryFilter:function(variable, start,end){ + this.provider.setFilter(variable,start,end) + + }, + /** * set the cartocss for the current renderer */ From a27b3aa5038631271ce5d08325a598467efd321b Mon Sep 17 00:00:00 2001 From: Stuart Lynn Date: Wed, 28 Oct 2015 18:49:21 -0400 Subject: [PATCH 3/4] Using one of Mamata's styles --- examples/tilejson.html | 143 ++++++++++++++++++++++++++++++++++------- 1 file changed, 118 insertions(+), 25 deletions(-) diff --git a/examples/tilejson.html b/examples/tilejson.html index 6c6c6a60..96fa650e 100644 --- a/examples/tilejson.html +++ b/examples/tilejson.html @@ -18,49 +18,142 @@ 'Map {', '-torque-time-attribute: "date";', '-torque-aggregation-function: "count(cartodb_id)";', - '-torque-frame-count: 760;', - '-torque-animation-duration: 15;', - '-torque-resolution: 2', + '-torque-frame-count: 1;', + '-torque-animation-duration: 1;', + '-torque-resolution: 0.25', + // '@8: #15f4ee;', + // '@10: white', '}', '#layer {', - ' marker-width: 3;', - ' marker-fill-opacity: 0.8;', - ' marker-fill: #FEE391; ', - ' comp-op: "lighten";', + + 'marker-opacity: 0.2;', + 'image-filters: colorize-alpha(#078c88,#15f4ee,#b7fcfa,#f8fffe);', + 'marker-line-width: 0;', + 'marker-fill: #2E5387;', + 'marker-allow-overlap: true;', + 'marker-width: 1;', + //'[zoom=4]{marker-width: 0.25;}', + //'[zoom=5]{marker-width: 0.75;}', + //'[zoom=6]{marker-width: 1.25;}', + //'[zoom=7]{marker-width: 1.5;}', + //'[zoom=8]{marker-width: 1.75;}', + //'[zoom=9]{marker-width: 2.0;}', + //'[zoom=10]{marker-width: 2.25;}', + // '[zoom=11]{marker-width: 2.5;marker-opacity:0.3;}', + // '[zoom=12]{marker-width: 2.75;marker-opacity:0.4;}', + // '[zoom=13]{marker-width: 3.0;marker-opacity:0.45;}', + // '[zoom=14]{marker-width: 3.25;marker-opacity:0.5;}', + // '[zoom=15]{marker-width: 0.75;marker-opacity:0.55;}', + // '[zoom=16]{marker-width: 4.0;marker-opacity:0.6;}', + // '[zoom>=17]{marker-width: 4.25;marker-opacity:0.65;}', + + /* + + ' [value > 2] { marker-fill: #FEC44F; }', - ' [value > 3] { marker-fill: #FE9929; }', - ' [value > 4] { marker-fill: #EC7014; }', - ' [value > 5] { marker-fill: #CC4C02; }', - ' [value > 6] { marker-fill: #993404; }', - ' [value > 7] { marker-fill: #662506; }', - ' [frame-offset = 1] { marker-width: 10; marker-fill-opacity: 0.05;}', - ' [frame-offset = 2] { marker-width: 15; marker-fill-opacity: 0.02;}', - '}' - ].join('\n'); - - + ' [value > 10] { marker-fill: #FE9929; }', + ' [value > 20] { marker-fill: #EC7014; }', + ' [value > 30] { marker-fill: #CC4C02; }', + ' [value > 40] { marker-fill: #993404; }', + ' [value > 50] { marker-fill: #662506; }', + */ + ] + + + + + // for(var i =0; i <255; i += 10){ + // var color = d3.scale.linear() + // .range() + // .range(["steelblue", "brown"]) + // .interpolate(d3.interpolateHcl); + // CARTOCSS.push("[value >= "+i+"]{marker-fill:"+color(i)+"};") + // } + + CARTOCSS.push("}") + CARTOCSS= CARTOCSS.join(" ") + + console.log(CARTOCSS) + + /* + ['Map {,', + '-torque-time-attribute: "date";,', + '-torque-aggregation-function: "count(cartodb_id)";,', + '-torque-frame-count: 6;,', + '-torque-animation-duration: 15;,', + '-torque-resolution: 1,', + '},', + '#layer {,', + 'marker-width: 1;,', + 'marker-fill-opacity: 1.0;,', + 'marker-fill: #FF2900; ,', + '[ value <= 20] { marker-fill: #0C2C84; } ', + '[ value <= 8] { marker-fill: #225EA8; }', + '[ value <= 4] { marker-fill: #1D91C0; }', + '[ value <= 3] { marker-fill: #41B6C4; }', + '[ value <= 2] { marker-fill: #7FCDBB; }', + '[ value <= 1] { marker-fill: #C7E9B4; }', + '[ value <= 0.1] { marker-fill: #FFFFCC; }', + '}'].join('\n') + */ + + var map = new L.Map('map', { zoomControl: true, center: [40, 0], - zoom: 3 + zoom: 0 }); + var hash = new L.Hash(map); - L.tileLayer('http://{s}.api.cartocdn.com/base-dark/{z}/{x}/{y}.png', { + L.tileLayer('http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', { attribution: 'CartoDB' }).addTo(map); var torqueLayer = new L.TorqueLayer({ - tileJSON: "http://localhost:4000/examples/tilejson.json", - cartocss: CARTOCSS + tileJSON: "http://bigdata.int.cartodb.net:8888/tile.json", + //tileJSON: "http://10.0.180.5:1234/", + cartocss: CARTOCSS, + valueDataType: Float32Array }); torqueLayer.error(function(err){ for(error in err){ - console.warn(err[error]); + console.warn([error]); } }); torqueLayer.addTo(map); - torqueLayer.play() + torqueLayer.setStep(0); + + + //torqueLayer.play() + window.torqueLayer = torqueLayer; + + function createHistogram(variable){ + var div_id = "histogram_"+variable; + $("#charts").append("") + + var chart = new cdb.geo.ui.Widget.Histogram.Chart( + {el:$("#"+div_id), + data:{values: [1,3,4,5,22,1,3], labels:[22, 34, 45, 67,100, 200, 300]}, + width: 300, + height:100, + y:0, + x:0}) + chart.render() + chart.show() + chart.bind("fliterChanged",function(start,end){ + console.log('setting filter', start,end ) + torqueLayer.setQueryFilter(variable, [start,end] ) + }) + + torqueLayer.addEventListener("histogramAdded",function(data){ + var data = torqueLayer.histogramForVariable(variable) + chart.reset(data) + }) + } + + createHistogram(0) + + - From 2b61a508b2af710725b0efd90265e29b57ca0f02 Mon Sep 17 00:00:00 2001 From: Stuart Lynn Date: Wed, 28 Oct 2015 18:50:41 -0400 Subject: [PATCH 4/4] adding in the histogram widget and supporting libraries --- examples/tilejson.html | 18 +- examples/vendor/backbone.js | 1894 + examples/vendor/cartodb.css | 2 + examples/vendor/cartodb.uncompressed.js | 55281 ++++++++++++++++++++++ examples/vendor/histogram-widget.js | 1277 + examples/vendor/leaflet-hash.js | 146 + examples/vendor/torque.category.css | 14 + examples/vendor/torque.category.js | 140 + examples/vendor/underscore.js | 1548 + 9 files changed, 60319 insertions(+), 1 deletion(-) create mode 100644 examples/vendor/backbone.js create mode 100644 examples/vendor/cartodb.css create mode 100644 examples/vendor/cartodb.uncompressed.js create mode 100644 examples/vendor/histogram-widget.js create mode 100644 examples/vendor/leaflet-hash.js create mode 100644 examples/vendor/torque.category.css create mode 100644 examples/vendor/torque.category.js create mode 100644 examples/vendor/underscore.js diff --git a/examples/tilejson.html b/examples/tilejson.html index 96fa650e..9866c2f2 100644 --- a/examples/tilejson.html +++ b/examples/tilejson.html @@ -1,16 +1,32 @@ + +
+
+ - + + + + +