Skip to content

Commit

Permalink
[Maps] expand extent filter to tile boundaries (#54276)
Browse files Browse the repository at this point in the history
* [Maps] expand extent filter to tile boundaries

* fix functional test

* simplify expandToTileBoundaries

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
nreese and elasticmachine committed Jan 14, 2020
1 parent 6c9e4ec commit 75d6842
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const ZOOM_TILE_KEY_INDEX = 0;
const X_TILE_KEY_INDEX = 1;
const Y_TILE_KEY_INDEX = 2;

function getTileCount(zoom) {
return Math.pow(2, zoom);
}

export function parseTileKey(tileKey) {
const tileKeyParts = tileKey.split('/');

Expand All @@ -21,7 +25,7 @@ export function parseTileKey(tileKey) {
const zoom = parseInt(tileKeyParts[ZOOM_TILE_KEY_INDEX], 10);
const x = parseInt(tileKeyParts[X_TILE_KEY_INDEX], 10);
const y = parseInt(tileKeyParts[Y_TILE_KEY_INDEX], 10);
const tileCount = Math.pow(2, zoom);
const tileCount = getTileCount(zoom);

if (x >= tileCount) {
throw new Error(
Expand Down Expand Up @@ -77,3 +81,34 @@ export function getTileBoundingBox(tileKey) {
right: tileToLongitude(x + 1, tileCount),
};
}

function sec(value) {
return 1 / Math.cos(value);
}

function latitudeToTile(lat, tileCount) {
const radians = (lat * Math.PI) / 180;
const y = ((1 - Math.log(Math.tan(radians) + sec(radians)) / Math.PI) / 2) * tileCount;
return Math.floor(y);
}

function longitudeToTile(lon, tileCount) {
const x = ((lon + 180) / 360) * tileCount;
return Math.floor(x);
}

export function expandToTileBoundaries(extent, zoom) {
const tileCount = getTileCount(zoom);

const upperLeftX = longitudeToTile(extent.minLon, tileCount);
const upperLeftY = latitudeToTile(Math.min(extent.maxLat, 90), tileCount);
const lowerRightX = longitudeToTile(extent.maxLon, tileCount);
const lowerRightY = latitudeToTile(Math.max(extent.minLat, -90), tileCount);

return {
minLon: tileToLongitude(upperLeftX, tileCount),
minLat: tileToLatitude(lowerRightY + 1, tileCount),
maxLon: tileToLongitude(lowerRightX + 1, tileCount),
maxLat: tileToLatitude(upperLeftY, tileCount),
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { parseTileKey, getTileBoundingBox } from './geo_tile_utils';
import { parseTileKey, getTileBoundingBox, expandToTileBoundaries } from './geo_tile_utils';

it('Should parse tile key', () => {
expect(parseTileKey('15/23423/1867')).toEqual({
Expand Down Expand Up @@ -34,3 +34,19 @@ it('Should convert tile key to geojson Polygon with extra precision', () => {
left: -73.9839292,
});
});

it('Should expand extent to align boundaries with tile boundaries', () => {
const extent = {
maxLat: 12.5,
maxLon: 102.5,
minLat: 2.5,
minLon: 92.5,
};
const tileAlignedExtent = expandToTileBoundaries(extent, 7);
expect(tileAlignedExtent).toEqual({
maxLat: 13.9234,
maxLon: 104.0625,
minLat: 0,
minLon: 90,
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import uuid from 'uuid/v4';
import { copyPersistentState } from '../../reducers/util';
import { ES_GEO_FIELD_TYPE, METRIC_TYPE } from '../../../common/constants';
import { DataRequestAbortError } from '../util/data_request';
import { expandToTileBoundaries } from './es_geo_grid_source/geo_tile_utils';

export class AbstractESSource extends AbstractVectorSource {
static icon = 'logoElasticsearch';
Expand Down Expand Up @@ -117,7 +118,10 @@ export class AbstractESSource extends AbstractVectorSource {
if (this.isFilterByMapBounds() && searchFilters.buffer) {
//buffer can be empty
const geoField = await this._getGeoField();
allFilters.push(createExtentFilter(searchFilters.buffer, geoField.name, geoField.type));
const buffer = this.isGeoGridPrecisionAware()
? expandToTileBoundaries(searchFilters.buffer, searchFilters.geogridPrecision)
: searchFilters.buffer;
allFilters.push(createExtentFilter(buffer, geoField.name, geoField.type));
}
if (isTimeAware) {
allFilters.push(timefilter.createFilter(indexPattern, searchFilters.timeFilters));
Expand Down
12 changes: 8 additions & 4 deletions x-pack/test/functional/page_objects/gis_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,16 @@ export function GisPageProvider({ getService, getPageObjects }) {
return links.length;
}

async isSetViewPopoverOpen() {
return await testSubjects.exists('mapSetViewForm', { timeout: 500 });
}

async openSetViewPopover() {
const isOpen = await testSubjects.exists('mapSetViewForm');
const isOpen = await this.isSetViewPopoverOpen();
if (!isOpen) {
await retry.try(async () => {
await testSubjects.click('toggleSetViewVisibilityButton');
const isOpenAfterClick = await testSubjects.exists('mapSetViewForm');
const isOpenAfterClick = await this.isSetViewPopoverOpen();
if (!isOpenAfterClick) {
throw new Error('set view popover not opened');
}
Expand All @@ -227,11 +231,11 @@ export function GisPageProvider({ getService, getPageObjects }) {
}

async closeSetViewPopover() {
const isOpen = await testSubjects.exists('mapSetViewForm');
const isOpen = await this.isSetViewPopoverOpen();
if (isOpen) {
await retry.try(async () => {
await testSubjects.click('toggleSetViewVisibilityButton');
const isOpenAfterClick = await testSubjects.exists('mapSetViewForm');
const isOpenAfterClick = await this.isSetViewPopoverOpen();
if (isOpenAfterClick) {
throw new Error('set view popover not closed');
}
Expand Down

0 comments on commit 75d6842

Please sign in to comment.