diff --git a/lib/cartodb/utils/style/turbo-carto-adapter.js b/lib/cartodb/utils/style/turbo-carto-adapter.js index fa754835..0c86d0c8 100644 --- a/lib/cartodb/utils/style/turbo-carto-adapter.js +++ b/lib/cartodb/utils/style/turbo-carto-adapter.js @@ -1,5 +1,7 @@ 'use strict'; +var dot = require('dot'); +dot.templateSettings.strip = false; var queue = require('queue-async'); var SubstitutionTokens = require('../substitution-tokens'); @@ -31,17 +33,49 @@ TurboCartoAdapter.prototype.getLayers = function (username, layers, callback) { }); }; +var bboxTemplate = dot.template('(select ST_SetSRID(st_extent(the_geom_webmercator), 3857) from ({{=it._sql}}) __c)'); +var zoomTemplate = dot.template([ + 'GREATEST(', + 'ceil(log(40075017000 / 256 / GREATEST(', + ' st_xmax({{=it._bbox}}) - st_xmin({{=it._bbox}}),', + ' st_ymax({{=it._bbox}}) - st_ymin({{=it._bbox}})', + '))/log(2)),', + '0', + ')' +].join('\n')); +var pixelSizeTemplate = dot.template('40075017 * cos(ST_Y(ST_Centroid({{=it._bbox}}))) / 2 ^ (({{=it._zoom}}) + 8)'); +var scaleDenominatorTemplate = dot.template('({{=it._pixelSize}} / 0.00028)::numeric'); + + TurboCartoAdapter.prototype._parseCartoCss = function (username, layer, callback) { if (!shouldParseLayerCartocss(layer)) { return callback(null, layer); } - var sql = SubstitutionTokens.replace(layer.options.sql, { + var tokens = { bbox: 'ST_MakeEnvelope(-20037508.34,-20037508.34,20037508.34,20037508.34,3857)', scale_denominator: '500000001', pixel_width: '156412', pixel_height: '156412' - }); + }; + + var layerSql = layer.options.sql; + var layerRawSql = layer.options.sql_raw; + if (SubstitutionTokens.hasTokens(layerSql) && layerRawSql) { + var bbox = bboxTemplate({ _sql: layerRawSql }); + var zoom = zoomTemplate({ _bbox: bbox }); + var pixelSize = pixelSizeTemplate({ _bbox: bbox, _zoom: zoom }); + var scaleDenominator = scaleDenominatorTemplate({ _pixelSize: pixelSize }); + + tokens = { + bbox: bbox, + scale_denominator: scaleDenominator, + pixel_width: pixelSize, + pixel_height: pixelSize + }; + } + + var sql = SubstitutionTokens.replace(layerSql, tokens); this.turboCartoParser.process(username, layer.options.cartocss, sql, function (err, cartocss) { // Only return turbo-carto errors