Skip to content

Commit

Permalink
Merge pull request elastic#8000 from thomasneirynck/fix/7882_zoom_pre…
Browse files Browse the repository at this point in the history
…cision

Change mapping from zoom levels to geohash precision

Former-commit-id: b98339b
  • Loading branch information
thomasneirynck authored Aug 17, 2016
2 parents 9dd9c3a + c06b6ab commit 9cdeab5
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 30 deletions.
64 changes: 64 additions & 0 deletions src/ui/public/agg_types/__tests__/buckets/_geo_hash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import expect from 'expect.js';
import AggTypesBucketsGeoHashProvider from 'ui/agg_types/buckets/geo_hash';

describe('Geohash Agg', function () {


describe('write', function () {

let paramWriter = new AggTypesBucketsGeoHashProvider(function PrivateMock() {
return function BucketMock(geohashProvider) {
return geohashProvider.params[4];
};
}, {
get: function () {
return 7;//"visualization:tileMap:maxPrecision"
}
});

describe('geohash', function () {

const zoomToGeoHashPrecision = {
0: 1,
1: 2,
2: 2,
3: 2,
4: 3,
5: 3,
6: 4,
7: 4,
8: 4,
9: 5,
10: 5,
11: 6,
12: 6,
13: 6,
14: 7,
15: 7,
16: 7,
17: 7,
18: 7,
19: 7,
20: 7,
21: 7
};

Object.keys(zoomToGeoHashPrecision).forEach((zoomLevel) => {
it(`zoom level ${zoomLevel} should correspond to correct geohash-precision`, () => {
const output = {params: {}};
paramWriter.write({
vis: {
hasUiState: () => true,
uiStateVal: () => zoomLevel
},
params: {
autoPrecision: true
}
}, output);
expect(output.params.precision).to.equal(zoomToGeoHashPrecision[zoomLevel]);
});
});
});

});
});
1 change: 1 addition & 0 deletions src/ui/public/agg_types/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import './agg_type';
import './agg_params';
import './bucket_count_between';
import './buckets/_histogram';
import './buckets/_geo_hash';
import './buckets/_range';
import AggTypesIndexProvider from 'ui/agg_types/index';
import AggTypesBucketsBucketAggTypeProvider from 'ui/agg_types/buckets/_bucket_agg_type';
Expand Down
58 changes: 28 additions & 30 deletions src/ui/public/agg_types/buckets/geo_hash.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
import _ from 'lodash';
import moment from 'moment';
import AggTypesBucketsBucketAggTypeProvider from 'ui/agg_types/buckets/_bucket_agg_type';
import precisionTemplate from 'ui/agg_types/controls/precision.html';
export default function GeoHashAggDefinition(Private, config) {
let BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider);
let defaultPrecision = 2;
import {geohashColumns} from 'ui/utils/decode_geo_hash';

// zoomPrecision maps event.zoom to a geohash precision value
// event.limit is the configurable max geohash precision
// default max precision is 7, configurable up to 12
const zoomPrecision = {
1: 2,
2: 2,
3: 2,
4: 3,
5: 3,
6: 4,
7: 4,
8: 5,
9: 5,
10: 6,
11: 6,
12: 7,
13: 7,
14: 8,
15: 9,
16: 10,
17: 11,
18: 12
};
export default function GeoHashAggDefinition(Private, config) {
const BucketAggType = Private(AggTypesBucketsBucketAggTypeProvider);
const defaultPrecision = 2;
const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12;
/**
* Map Leaflet zoom levels to geohash precision levels.
* The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide.
*/
let zoomPrecision = {};
const minGeohashPixels = 16;
for (let zoom = 0; zoom <= 21; zoom += 1) {
const worldPixels = 256 * Math.pow(2, zoom);
zoomPrecision[zoom] = 1;
for (let precision = 2; precision <= maxPrecision; precision += 1) {
const columns = geohashColumns(precision);
if ((worldPixels / columns) >= minGeohashPixels) {
zoomPrecision[zoom] = precision;
} else {
break;
}
}
}

function getPrecision(precision) {
let maxPrecision = _.parseInt(config.get('visualization:tileMap:maxPrecision'));

precision = parseInt(precision, 10);

Expand Down Expand Up @@ -75,8 +70,11 @@ export default function GeoHashAggDefinition(Private, config) {
},
write: function (aggConfig, output) {
const vis = aggConfig.vis;
const currZoom = vis.hasUiState() && vis.uiStateVal('mapZoom');
const autoPrecisionVal = zoomPrecision[(currZoom || vis.params.mapZoom)];
let currZoom;
if (vis.hasUiState()) {
currZoom = parseInt(vis.uiStateVal('mapZoom'), 10);
}
const autoPrecisionVal = zoomPrecision[currZoom >= 0 ? currZoom : parseInt(vis.params.mapZoom)];
output.params.precision = aggConfig.params.autoPrecision ? autoPrecisionVal : getPrecision(aggConfig.params.precision);
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/ui/public/utils/__tests__/decode_geo_hash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import expect from 'expect.js';
import {geohashColumns} from 'ui/utils/decode_geo_hash';

describe('decode_geo_hash', function () {
it('geohashColumns', function () {
expect(geohashColumns(1)).to.equal(8);
expect(geohashColumns(2)).to.equal(8 * 4);
expect(geohashColumns(3)).to.equal(8 * 4 * 8);
expect(geohashColumns(4)).to.equal(8 * 4 * 8 * 4);
});
});
26 changes: 26 additions & 0 deletions src/ui/public/utils/decode_geo_hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,29 @@ function refine_interval(interval, cd, mask) {
}

export default decodeGeoHash;


/**
* Get the number of geohash cells for a given precision
*
* @param {number} precision the geohash precision (1<=precision<=12).
* @param {number} axis constant for the axis 0=lengthwise (ie. columns, along longitude), 1=heightwise (ie. rows, along latitude).
* @returns {number} Number of geohash cells (rows or columns) at that precision
*/
function geohashCells(precision, axis) {
let cells = 1;
for (let i = 1; i <= precision; i += 1) {
//On odd precisions, rows divide by 4 and columns by 8. Vice-versa on even precisions.
cells *= (i % 2 === axis) ? 4 : 8;
}
return cells;
}

/**
* Get the number of geohash columns (world-wide) for a given precision
* @param precision the geohash precision
* @returns {number} the number of columns
*/
export function geohashColumns(precision) {
return geohashCells(precision, 0);
}

0 comments on commit 9cdeab5

Please sign in to comment.