Use bounding box of dataviews to select overviews level
This commit is contained in:
@@ -136,13 +136,17 @@ DataviewBackend.prototype.getDataview = function (mapConfigProvider, user, param
|
||||
);
|
||||
}
|
||||
}
|
||||
var dataviewFactory = DataviewFactoryWithOverviews.getFactory(overviewsQueryRewriter, queryRewriteData);
|
||||
|
||||
if (params.bbox) {
|
||||
var bboxFilter = new BBoxFilter({column: 'the_geom', srid: 4326}, {bbox: params.bbox});
|
||||
query = bboxFilter.sql(query);
|
||||
queryRewriteData = _.extend(queryRewriteData, { bbox_filter: bboxFilter });
|
||||
}
|
||||
|
||||
var dataviewFactory = DataviewFactoryWithOverviews.getFactory(
|
||||
overviewsQueryRewriter, queryRewriteData, { bbox: params.bbox }
|
||||
);
|
||||
|
||||
var overrideParams = _.reduce(_.pick(params, 'start', 'end', 'bins'),
|
||||
function castNumbers(overrides, val, k) {
|
||||
overrides[k] = Number.isFinite(+val) ? +val : val;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
var parentFactory = require('../factory');
|
||||
var dataviews = require('./');
|
||||
|
||||
function OverviewsDataviewFactory(queryRewriter, queryRewriteData) {
|
||||
function OverviewsDataviewFactory(queryRewriter, queryRewriteData, options) {
|
||||
this.queryRewriter = queryRewriter;
|
||||
this.queryRewriteData = queryRewriteData;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
OverviewsDataviewFactory.prototype.getDataview = function(query, dataviewDefinition) {
|
||||
@@ -12,7 +13,9 @@ OverviewsDataviewFactory.prototype.getDataview = function(query, dataviewDefinit
|
||||
if ( !this.queryRewriter || !this.queryRewriteData || !dataviews[type] ) {
|
||||
return parentFactory.getDataview(query, dataviewDefinition);
|
||||
}
|
||||
return new dataviews[type](query, dataviewDefinition.options, this.queryRewriter, this.queryRewriteData);
|
||||
return new dataviews[type](
|
||||
query, dataviewDefinition.options, this.queryRewriter, this.queryRewriteData, this.options
|
||||
);
|
||||
};
|
||||
|
||||
var OverviewsDataviewMetaFactory = {
|
||||
@@ -21,8 +24,8 @@ var OverviewsDataviewMetaFactory = {
|
||||
return allDataviews;
|
||||
}, {}),
|
||||
|
||||
getFactory: function(queryRewriter, queryRewriteData) {
|
||||
return new OverviewsDataviewFactory(queryRewriter, queryRewriteData);
|
||||
getFactory: function(queryRewriter, queryRewriteData, options) {
|
||||
return new OverviewsDataviewFactory(queryRewriter, queryRewriteData, options);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
var _ = require('underscore');
|
||||
var BaseWidget = require('../base');
|
||||
var BaseDataview = require('../formula');
|
||||
|
||||
@@ -27,13 +28,14 @@ var formulaQueryTpls = {
|
||||
].join('\n')),
|
||||
};
|
||||
|
||||
function Formula(query, options, queryRewriter, queryRewriteData) {
|
||||
function Formula(query, options, queryRewriter, queryRewriteData, params) {
|
||||
this.base_dataview = new BaseDataview(query, options);
|
||||
this.query = query;
|
||||
this.column = options.column || '1';
|
||||
this.operation = options.operation;
|
||||
this.queryRewriter = queryRewriter;
|
||||
this.queryRewriteData = queryRewriteData;
|
||||
this.options = params;
|
||||
}
|
||||
|
||||
Formula.prototype = new BaseWidget();
|
||||
@@ -41,21 +43,39 @@ Formula.prototype.constructor = Formula;
|
||||
|
||||
module.exports = Formula;
|
||||
|
||||
var zoom_level_factor = 100.0;
|
||||
|
||||
// Compute zoom level so that the the resolution grid size of the
|
||||
// selected overview is smaller (zoom_level_factor times smaller at least)
|
||||
// than the bounding box size.
|
||||
function zoom_level_for_bbox(bbox) {
|
||||
var px_per_tile = 256.0;
|
||||
var earth_width = 360.0;
|
||||
// TODO: now we assume overviews are computed for 1-pixel tolerance;
|
||||
// should use extended overviews metadata to compute this properly.
|
||||
if ( bbox ) {
|
||||
var bbox_values = _.map(bbox.split(','), function(v) { return +v; });
|
||||
// TODO: look at possible crossing-180º issues
|
||||
var w = Math.abs(bbox_values[2]-bbox_values[0]);
|
||||
var h = Math.abs(bbox_values[3]-bbox_values[1]);
|
||||
var max_dim = Math.min(w, h);
|
||||
|
||||
// Find minimum suitable z
|
||||
// note that the QueryRewirter will use the minimum level overview
|
||||
// of level >= z if it exists, and otherwise the base table
|
||||
var z = Math.ceil(-Math.log(max_dim*px_per_tile/earth_width/zoom_level_factor)/Math.log(2.0));
|
||||
return Math.max(z, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Formula.prototype.sql = function(psql, filters, override, callback) {
|
||||
var _query = this.query;
|
||||
var formulaQueryTpl = formulaQueryTpls[this.operation];
|
||||
|
||||
if ( formulaQueryTpl ) {
|
||||
// supported formula for use with overviews
|
||||
|
||||
// TODO: determine zoom level using bounding box so that the resolution
|
||||
// (grid size) of the overview much smaller thatn the bounding box.
|
||||
// This could be left to be computed by the queryRewriter passing the
|
||||
// bounding box to it.
|
||||
// The bounding box could be passed to the dataview constructor, or
|
||||
// it could b extracted from the query.
|
||||
var zoom_level = 0;
|
||||
|
||||
var zoom_level = zoom_level_for_bbox(this.options.bbox);
|
||||
_query = this.queryRewriter.query(_query, this.queryRewriteData, { zoom_level: zoom_level });
|
||||
var formulaSql = formulaQueryTpl({
|
||||
_query: _query,
|
||||
@@ -64,6 +84,7 @@ Formula.prototype.sql = function(psql, filters, override, callback) {
|
||||
});
|
||||
debug(formulaSql);
|
||||
callback = callback || override;
|
||||
|
||||
return callback(null, formulaSql);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,14 @@ var TableNameParser = require('./table_name_parser');
|
||||
|
||||
// this is meant as a hack for development
|
||||
var queryBuilder = require('camshaft/lib/filter/query-builder');
|
||||
function apply_filters_to_query(query, filters) {
|
||||
function apply_filters_to_query(query, filters, bbox_filter) {
|
||||
// TODO: implement filter application here
|
||||
if ( filters && !_.isEmpty(filters)) {
|
||||
query = queryBuilder.getSql(query, filters);
|
||||
}
|
||||
if ( bbox_filter ) {
|
||||
query = bbox_filter.sql(query);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
@@ -227,6 +230,7 @@ OverviewsQueryRewriter.prototype.query = function(query, data, options) {
|
||||
var overviews = data && data.overviews;
|
||||
var unfiltered_query = data && data.unfiltered_query;
|
||||
var filters = data && data.filters;
|
||||
var bbox_filter = data && data.bbox_filter;
|
||||
|
||||
if ( !unfiltered_query ) {
|
||||
unfiltered_query = query;
|
||||
@@ -252,7 +256,7 @@ OverviewsQueryRewriter.prototype.query = function(query, data, options) {
|
||||
// Applicability of the filters should depend both on the expected
|
||||
// row count of the result and on the columns to be filter and the
|
||||
// way they're agregated in overviews.
|
||||
rewritten_query = apply_filters_to_query(rewritten_query, filters);
|
||||
rewritten_query = apply_filters_to_query(rewritten_query, filters, bbox_filter);
|
||||
}
|
||||
|
||||
return rewritten_query;
|
||||
|
||||
Reference in New Issue
Block a user