Aggregation: Style improvements

This commit is contained in:
Raul Marin
2019-07-16 12:49:09 +02:00
parent 286daa9bec
commit de49aa0bd4
3 changed files with 29 additions and 24 deletions
+3 -3
View File
@@ -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 => `
@@ -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}"');
}
};
+6 -6
View File
@@ -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,