diff --git a/lib/torque/gmaps/torque.js b/lib/torque/gmaps/torque.js index a72c017..958ab72 100644 --- a/lib/torque/gmaps/torque.js +++ b/lib/torque/gmaps/torque.js @@ -74,6 +74,9 @@ GMapsTorqueLayer.prototype = _.extend({}, bounds: self.provider.getBounds() }); self.animator.rescale(); + self.fire('change:steps', { + steps: self.provider.getSteps() + }); self.setKey(self.key); }; @@ -121,9 +124,6 @@ GMapsTorqueLayer.prototype = _.extend({}, this.provider && this.provider.setSteps(steps); this.animator && this.animator.steps(steps); this._reloadTiles(); - this.fire('change:steps', { - steps: steps - }); }, setColumn: function(column, isTime) { @@ -206,7 +206,7 @@ GMapsTorqueLayer.prototype = _.extend({}, stepToTime: function(step) { if (!this.provider) return 0; var times = this.provider.getKeySpan(); - var time = times.start + (times.end - times.start)*(step/this.options.steps); + var time = times.start + (times.end - times.start)*(step/this.provider.getSteps()); return new Date(time); }, diff --git a/lib/torque/leaflet/torque.js b/lib/torque/leaflet/torque.js index 6332ae7..7d050f4 100644 --- a/lib/torque/leaflet/torque.js +++ b/lib/torque/leaflet/torque.js @@ -47,6 +47,18 @@ L.TorqueLayer = L.CanvasLayer.extend({ this.options.renderer = this.options.renderer || 'point'; this.options.provider = this.options.provider || 'sql_api'; + options.ready = function() { + self.fire("change:bounds", { + bounds: self.provider.getBounds() + }); + self.animator.steps(self.provider.getSteps()); + self.animator.rescale(); + self.fire('change:steps', { + steps: self.provider.getSteps() + }); + self.setKey(self.key); + }; + this.provider = new this.providers[this.options.provider](options); this.renderer = new this.renderers[this.options.renderer](this.getCanvas(), options); @@ -59,13 +71,6 @@ L.TorqueLayer = L.CanvasLayer.extend({ }); }, this); - this.options.ready = function() { - self.fire("change:bounds", { - bounds: self.provider.getBounds() - }); - self.animator.rescale(); - self.setKey(self.key); - }; }, @@ -104,11 +109,7 @@ L.TorqueLayer = L.CanvasLayer.extend({ setSteps: function(steps) { this.provider.setSteps(steps); - this.animator.steps(steps); this._reloadTiles(); - this.fire('change:steps', { - steps: steps - }) }, setColumn: function(column, isTime) { @@ -177,7 +178,7 @@ L.TorqueLayer = L.CanvasLayer.extend({ */ stepToTime: function(step) { var times = this.provider.getKeySpan(); - var time = times.start + (times.end - times.start)*(step/this.options.steps); + var time = times.start + (times.end - times.start)*(step/this.provider.getSteps()); return new Date(time); }, diff --git a/lib/torque/provider.json.js b/lib/torque/provider.json.js index 6463675..4acb638 100644 --- a/lib/torque/provider.json.js +++ b/lib/torque/provider.json.js @@ -286,11 +286,17 @@ } }, + getSteps: function() { + return Math.min(this.options.steps, this.options.data_steps); + }, + setSteps: function(steps) { if (this.options.steps !== steps) { this.options.steps = steps; - this.options.step = (this.options.end- this.options.start)/this.options.steps; + this.options.step = (this.options.end - this.options.start)/this.getSteps(); this.options.step = this.options.step || 1; + this._ready = false; + this._fetchKeySpan(); } }, @@ -322,9 +328,11 @@ self.options.extra_params.last_updated = data.rows[0].updated_at || 0; self.options.is_time = data.fields[self.options.column].type === 'date'; + var column_conv = self.options.column; if (self.options.is_time){ max_tmpl = "date_part('epoch', max({column}))"; min_tmpl = "date_part('epoch', min({column}))"; + column_conv = format("date_part('epoch', {column})", self.options); } else { max_tmpl = "max({column})"; min_tmpl = "min({column})"; @@ -333,18 +341,47 @@ max_col = format(max_tmpl, { column: self.options.column }); min_col = format(min_tmpl, { column: self.options.column }); - var sql = format("SELECT st_xmax(st_envelope(st_collect(the_geom))) xmax,st_ymax(st_envelope(st_collect(the_geom))) ymax, st_xmin(st_envelope(st_collect(the_geom))) xmin, st_ymin(st_envelope(st_collect(the_geom))) ymin, {max_col} max, {min_col} min FROM ({sql}) __torque_wrap_sql", { + var sql_stats = "" + + "WITH summary_groups as ( " + + "WITH summary as ( " + + "select (row_number() over (order by __time_col asc nulls last)+1)/2 as rownum, __time_col " + + "from (select *, {column} as __time_col from ({sql}) __s) __torque_wrap_sql " + + "order by __time_col asc " + + ") " + + "SELECT " + + "max(__time_col) OVER(PARTITION BY rownum) - " + + "min(__time_col) OVER(PARTITION BY rownum) diff " + + "FROM summary " + + "), subq as ( " + + " SELECT " + + "st_xmax(st_envelope(st_collect(the_geom))) xmax, " + + "st_ymax(st_envelope(st_collect(the_geom))) ymax, " + + "st_xmin(st_envelope(st_collect(the_geom))) xmin, " + + "st_ymin(st_envelope(st_collect(the_geom))) ymin, " + + "{max_col} max, " + + "{min_col} min FROM ({sql}) __torque_wrap_sql " + + ")" + + "SELECT " + + "xmax, xmin, ymax, ymin, a.max as max_date, a.min as min_date, " + + "avg(diff) as diffavg," + + "(a.max - a.min)/avg(diff) as num_steps " + + "FROM summary_groups, subq a " + + "WHERE diff > 0 group by xmax, xmin, ymax, ymin, max_date, min_date"; + + var sql = format(sql_stats, { max_col: max_col, min_col: min_col, + column: column_conv, sql: self.getSQL() }); self.sql(sql, function(data) { //TODO: manage bounds data = data.rows[0]; - self.options.start = data.min; - self.options.end = data.max; - self.options.step = (data.max - data.min)/self.options.steps; + self.options.start = data.min_date; + self.options.end = data.max_date; + self.options.step = (data.max_date - data.min_date)/Math.min(self.options.steps, data.num_steps>>0); + self.options.data_steps = data.num_steps >> 0; // step can't be 0 self.options.step = self.options.step || 1; self.options.bounds = [