diff --git a/lib/cartodb/backends/cluster.js b/lib/cartodb/backends/cluster.js index 62ef86a9..24145b8d 100644 --- a/lib/cartodb/backends/cluster.js +++ b/lib/cartodb/backends/cluster.js @@ -6,7 +6,7 @@ const debug = require('debug')('backend:cluster'); const AggregationMapConfig = require('../models/aggregation/aggregation-mapconfig'); const windshaftUtils = require('windshaft').utils; -const wmh = new windshaftUtils.WebMercatorHelper(); +const webmercator = new windshaftUtils.WebMercatorHelper(); module.exports = class ClusterBackend { getClusterFeatures (mapConfigProvider, params, callback) { @@ -159,8 +159,8 @@ const clusterFeaturesQuery = ctx => ` `; const gridResolution = ctx => { - const zoom_resolution = wmh.getResolution({ z : Math.min(38, ctx.zoom) }); - return `${256/ctx.res} * (${zoom_resolution})::double precision`; + const zoomResolution = webmercator.getResolution({ z : Math.min(38, ctx.zoom) }); + return `${256/ctx.res} * (${zoomResolution})::double precision`; }; const aggregationQuery = ctx => ` diff --git a/lib/cartodb/models/aggregation/aggregation-query.js b/lib/cartodb/models/aggregation/aggregation-query.js index 6fd416c5..c70ec9dc 100644 --- a/lib/cartodb/models/aggregation/aggregation-query.js +++ b/lib/cartodb/models/aggregation/aggregation-query.js @@ -3,6 +3,8 @@ const timeDimension = require('./time-dimension'); const DEFAULT_PLACEMENT = 'point-sample'; +const windshaftUtils = require('windshaft').utils; +const webmercator = new windshaftUtils.WebMercatorHelper(); function optionsToParams (options) { return { @@ -265,16 +267,18 @@ const havingClause = ctx => { // We limit the the minimum resolution to avoid division by zero problems. The limit used is // the pixel size of zoom level 30 (i.e. 1/2*(30+8) of the full earth web-mercator extent), which is about 0.15 mm. // -// NOTE: We'd rather use !scale_denominator!, but in Mapnik this value is extent / 256 for raster +// NOTE: We'd rather use !pixel_width!, but in Mapnik this value is extent / 256 for raster // and extent / tile_extent {4096 default} for MVT, so since aggregations are always based // on 256 we can't have the same query in both cases // As this scale change doesn't happen in !scale_denominator! we use that instead +// NOTE 2: The 0.00028 is used in Mapnik (and replicated in pg-mvt) and comes from +// OGC's Styled Layer Descriptor Implementation Specification const gridResolution = ctx => { - const minimumResolution = 2*Math.PI*6378137/Math.pow(2,38); + const minimumResolution = webmercator.getResolution({ z : 38 }); return `${256/ctx.res} * GREATEST(!scale_denominator! * 0.00028, ${minimumResolution})::double precision`; }; -// SQL query to extra the boundaries of the area to be aggregated and the grid resolution +// SQL query to extract the boundaries of the area to be aggregated and the grid resolution // cdb_{x-y}{min_max} return the limits of the tile. Aggregations do [min, max) in both axis // cdb_res: Aggregation resolution (as specified by gridResolution) // cdb_point_bbox: Tile bounding box [min, max] @@ -311,17 +315,17 @@ const aggregatedPointWebMercator = (ctx) => { switch (ctx.placement) { // For centroid, we return the average of the cell - case `centroid`: - return `, ST_SetSRID(ST_MakePoint(AVG(cdb_x), AVG(cdb_y)), 3857) AS the_geom_webmercator`; + case 'centroid': + return ', ST_SetSRID(ST_MakePoint(AVG(cdb_x), AVG(cdb_y)), 3857) AS the_geom_webmercator'; // Middle point of the cell - case `point-grid`: + case 'point-grid': return `, ST_SetSRID(ST_MakePoint(cdb_pos_grid_x, cdb_pos_grid_y), 3857) AS the_geom_webmercator`; // For point-sample we'll get a single point directly from the source // If it's default aggregation we'll add the extra columns to keep backwards compatibility - case `point-sample`: - return ``; + case 'point-sample': + return ''; default: throw new Error(`Invalid aggregation placement "${ctx.placement}`); @@ -332,16 +336,17 @@ const aggregatedPointWebMercator = (ctx) => { const aggregatedPointJoin = (ctx) => { switch (ctx.placement) { - case `centroid`: - return ``; + case 'centroid': + return ''; - case `point-grid`: - return ``; + case 'point-grid': + return ''; // For point-sample we'll get a single point directly from the source // If it's default aggregation we'll add the extra columns to keep backwards compatibility - case `point-sample`: - return `NATURAL JOIN + case 'point-sample': + return ` +NATURAL JOIN ( SELECT ${ctx.isDefaultAggregation ? `*` : `cartodb_id, the_geom_webmercator`} FROM @@ -352,7 +357,7 @@ const aggregatedPointJoin = (ctx) => { `; default: - throw new Error(`Invalid aggregation placement "${ctx.placement}`); + throw new Error('Invalid aggregation placement "${ctx.placement}"'); } }; diff --git a/test/acceptance/aggregation.js b/test/acceptance/aggregation.js index ea3f0261..c722a23c 100644 --- a/test/acceptance/aggregation.js +++ b/test/acceptance/aggregation.js @@ -7,7 +7,7 @@ const TestClient = require('../support/test-client'); const serverOptions = require('../../lib/cartodb/server_options'); const windshaftUtils = require('windshaft').utils; -const wmh = new windshaftUtils.WebMercatorHelper(); +const webmercator = new windshaftUtils.WebMercatorHelper(); const suites = [ { @@ -112,15 +112,15 @@ describe('aggregation', function () { WITH hgrid AS ( SELECT CDB_RectangleGrid ( - ST_Expand(!bbox!, ${wmh.getResolution({ z : 1 })} * 12), - ${wmh.getResolution({ z : 1 })} * 12, - ${wmh.getResolution({ z : 1 })} * 12 + ST_Expand(!bbox!, ${webmercator.getResolution({ z : 1 })} * 12), + ${webmercator.getResolution({ z : 1 })} * 12, + ${webmercator.getResolution({ z : 1 })} * 12 ) as cell ) SELECT hgrid.cell as the_geom_webmercator, count(1) as agg_value, - count(1) /power( 12 * ${wmh.getResolution({ z : 1 })}, 2 ) as agg_value_density, + count(1) /power( 12 * ${webmercator.getResolution({ z : 1 })}, 2 ) as agg_value_density, row_number() over () as cartodb_id FROM hgrid, (<%= sql %>) i WHERE ST_Intersects(i.the_geom_webmercator, hgrid.cell) GROUP BY hgrid.cell @@ -207,7 +207,7 @@ describe('aggregation', function () { // const POINTS_SQL_GRID = (z, resolution) => ` WITH params AS ( - SELECT ${wmh.getResolution({ z : z })}*${resolution} AS l -- cell size for Z, resolution + SELECT ${webmercator.getResolution({ z : z })}*${resolution} AS l -- cell size for Z, resolution ) SELECT row_number() OVER () AS cartodb_id,