Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Maps] Add super-fine option to grid/cluster layers #76526

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
64d439b
boilerplate
thomasneirynck Sep 2, 2020
c21d565
more boilerplate
thomasneirynck Sep 2, 2020
abf23ca
even more boilerplate
thomasneirynck Sep 2, 2020
d5e882d
add round-trip boilerplate
thomasneirynck Sep 2, 2020
416ed56
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 7, 2020
6b04156
move to common
thomasneirynck Sep 8, 2020
3f42ffe
move more files
thomasneirynck Sep 8, 2020
46e162a
move more utils
thomasneirynck Sep 8, 2020
3a67982
reuse existing implementation
thomasneirynck Sep 8, 2020
0df9b29
fix autodomain
thomasneirynck Sep 8, 2020
b1aa692
minor fixes
thomasneirynck Sep 8, 2020
2d84c57
undo typo
thomasneirynck Sep 8, 2020
9bb547f
enable grids
thomasneirynck Sep 8, 2020
a63d8a7
add shape support
thomasneirynck Sep 8, 2020
ee0f4d0
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 8, 2020
2342a35
create util folder
thomasneirynck Sep 8, 2020
b986964
remove some dupe
thomasneirynck Sep 8, 2020
86105f4
not done
thomasneirynck Sep 8, 2020
9693042
add new api extension
thomasneirynck Sep 8, 2020
3d28a58
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 9, 2020
01ed2d3
reuse implementation
thomasneirynck Sep 9, 2020
eecef6c
ts fixes
thomasneirynck Sep 9, 2020
9aa2038
type fixes
thomasneirynck Sep 9, 2020
9428aa1
more type fixes
thomasneirynck Sep 9, 2020
16f26d2
more type fixes
thomasneirynck Sep 9, 2020
b3bd0f1
remove cruft
thomasneirynck Sep 9, 2020
a148f5c
remove log
thomasneirynck Sep 9, 2020
db23dc5
remove dupes
thomasneirynck Sep 9, 2020
1ed2b67
simplification
thomasneirynck Sep 9, 2020
270f82c
reuse existing tile parsing
thomasneirynck Sep 9, 2020
751a39b
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 10, 2020
989f767
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 10, 2020
4e71f48
review feedback
thomasneirynck Sep 10, 2020
348a7ab
remove param
thomasneirynck Sep 10, 2020
0d5d0b6
remove fluffy try-catch
thomasneirynck Sep 10, 2020
7c642bf
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 14, 2020
a3946de
Add deprecation message to coordinate map and region map
nreese Sep 14, 2020
bbf755f
clean up text
nreese Sep 15, 2020
8c61d70
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 16, 2020
b773bb3
remove interfaces
thomasneirynck Sep 16, 2020
1e672ad
Merge branch 'master' of github.com:elastic/kibana into deprecation_m…
nreese Sep 16, 2020
1b5a900
add default distro link and view in maps link
nreese Sep 16, 2020
7571e3d
move url generation into onClick handler
nreese Sep 16, 2020
7ab105b
create tile map layer descritor
nreese Sep 16, 2020
a18083c
set metrics and color and scaling
nreese Sep 17, 2020
820acb3
lazy load createTileMapLayerDescriptor
nreese Sep 17, 2020
c9fa756
tslint fixes
nreese Sep 17, 2020
33f205e
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 17, 2020
99ca7d8
remove things
thomasneirynck Sep 18, 2020
fbecaf8
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 18, 2020
cfc4d21
add unit tests
thomasneirynck Sep 18, 2020
bb478aa
add unit tests
thomasneirynck Sep 18, 2020
45d587b
tslint cleanup for OSS code
nreese Sep 18, 2020
9fce05d
add snapshot
thomasneirynck Sep 18, 2020
070fac2
Merge branch 'deprecation_message' of https://github.com/nreese/kiban…
thomasneirynck Sep 18, 2020
5ad5585
Merge branch 'master' of github.com:elastic/kibana into maps/es_mvt_g…
thomasneirynck Sep 22, 2020
debec1e
feedback
thomasneirynck Sep 22, 2020
0b9fe76
make use of currentLayerType consistent
thomasneirynck Sep 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions x-pack/plugins/maps/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const FONTS_API_PATH = `${GIS_API_PATH}/fonts`;
export const API_ROOT_PATH = `/${GIS_API_PATH}`;

export const MVT_GETTILE_API_PATH = 'mvt/getTile';
export const MVT_GETGRIDTILE_API_PATH = 'mvt/getGridTile';
export const MVT_SOURCE_LAYER_NAME = 'source_layer';
export const KBN_TOO_MANY_FEATURES_PROPERTY = '__kbn_too_many_features__';
export const KBN_TOO_MANY_FEATURES_IMAGE_ID = '__kbn_too_many_features_image_id__';
Expand Down Expand Up @@ -165,8 +166,13 @@ export enum GRID_RESOLUTION {
COARSE = 'COARSE',
FINE = 'FINE',
MOST_FINE = 'MOST_FINE',
SUPER_FINE = 'SUPER_FINE',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is beyond the scope of this PR, but I wonder if we can have a range slider option next to the hard-coded select box values for advanced users to fine-tune their resolution?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will create follow-up issue for this after this merges.

}

export const SUPER_FINE_ZOOM_DELTA = 7; // (2 ^ SUPER_FINE_ZOOM_DELTA) ^ 2 = number of cells in a given tile
export const GEOTILE_GRID_AGG_NAME = 'gridSplit';
export const GEOCENTROID_AGG_NAME = 'gridCentroid';

export const TOP_TERM_PERCENTAGE_SUFFIX = '__percentage';

export const COUNT_PROP_LABEL = i18n.translate('xpack.maps.aggs.defaultCountLabel', {
Expand Down Expand Up @@ -230,8 +236,6 @@ export enum SCALING_TYPES {
MVT = 'MVT',
}

export const RGBA_0000 = 'rgba(0,0,0,0)';

export enum MVT_FIELD_TYPE {
STRING = 'String',
NUMBER = 'Number',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Feature } from 'geojson';
import { RENDER_AS } from '../constants';

export function convertCompositeRespToGeoJson(esResponse: any, renderAs: RENDER_AS): Feature[];
export function convertRegularRespToGeoJson(esResponse: any, renderAs: RENDER_AS): Feature[];
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
*/

import _ from 'lodash';
import { RENDER_AS } from '../../../../common/constants';
import { getTileBoundingBox } from './geo_tile_utils';
import { extractPropertiesFromBucket } from '../../util/es_agg_utils';
import { clamp } from '../../../../common/elasticsearch_geo_utils';
import { RENDER_AS, GEOTILE_GRID_AGG_NAME, GEOCENTROID_AGG_NAME } from '../constants';
import { getTileBoundingBox } from '../geo_tile_utils';
import { extractPropertiesFromBucket } from './es_agg_utils';
import { clamp } from './elasticsearch_geo_utils';

const GRID_BUCKET_KEYS_TO_IGNORE = ['key', 'gridCentroid'];
const GRID_BUCKET_KEYS_TO_IGNORE = ['key', GEOCENTROID_AGG_NAME];

export function convertCompositeRespToGeoJson(esResponse, renderAs) {
return convertToGeoJson(
Expand All @@ -20,7 +20,7 @@ export function convertCompositeRespToGeoJson(esResponse, renderAs) {
return _.get(esResponse, 'aggregations.compositeSplit.buckets', []);
},
(gridBucket) => {
return gridBucket.key.gridSplit;
return gridBucket.key[GEOTILE_GRID_AGG_NAME];
}
);
}
Expand All @@ -30,7 +30,7 @@ export function convertRegularRespToGeoJson(esResponse, renderAs) {
esResponse,
renderAs,
(esResponse) => {
return _.get(esResponse, 'aggregations.gridSplit.buckets', []);
return _.get(esResponse, `aggregations.${GEOTILE_GRID_AGG_NAME}.buckets`, []);
},
(gridBucket) => {
return gridBucket.key;
Expand All @@ -49,7 +49,7 @@ function convertToGeoJson(esResponse, renderAs, pluckGridBuckets, pluckGridKey)
type: 'Feature',
geometry: rowToGeometry({
gridKey,
gridCentroid: gridBucket.gridCentroid,
[GEOCENTROID_AGG_NAME]: gridBucket[GEOCENTROID_AGG_NAME],
renderAs,
}),
id: gridKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

jest.mock('../../../kibana_services', () => {});

// @ts-ignore
import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson';
import { RENDER_AS } from '../../../../common/constants';
import { RENDER_AS } from '../constants';

describe('convertCompositeRespToGeoJson', () => {
const esResponse = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/

import { FeatureCollection, GeoJsonProperties } from 'geojson';
import { MapExtent } from './descriptor_types';
import { ES_GEO_FIELD_TYPE } from './constants';
import { MapExtent } from '../descriptor_types';
import { ES_GEO_FIELD_TYPE } from '../constants';

export function scaleBounds(bounds: MapExtent, scaleFactor: number): MapExtent;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import {
POLYGON_COORDINATES_EXTERIOR_INDEX,
LON_INDEX,
LAT_INDEX,
} from '../common/constants';
import { getEsSpatialRelationLabel } from './i18n_getters';
import { FILTERS } from '../../../../src/plugins/data/common';
} from '../constants';
import { getEsSpatialRelationLabel } from '../i18n_getters';
import { FILTERS } from '../../../../../src/plugins/data/common';
import turfCircle from '@turf/circle';

const SPATIAL_FILTER_TYPE = FILTERS.SPATIAL_FILTER;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/
import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import { IndexPattern, IFieldType } from '../../../../../../src/plugins/data/public';
import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants';
import { IndexPattern, IFieldType } from '../../../../../src/plugins/data/common';
import { TOP_TERM_PERCENTAGE_SUFFIX } from '../constants';

export function getField(indexPattern: IndexPattern, fieldName: string) {
const field = indexPattern.fields.getByName(fieldName);
Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/maps/common/elasticsearch_util/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

export * from './es_agg_utils';
export * from './convert_to_geojson';
export * from './elasticsearch_geo_utils';
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

jest.mock('../../../kibana_services', () => {});

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

it('Should parse tile key', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,32 @@
*/

import _ from 'lodash';
import { DECIMAL_DEGREES_PRECISION } from '../../../../common/constants';
import { clampToLatBounds } from '../../../../common/elasticsearch_geo_utils';
import { DECIMAL_DEGREES_PRECISION } from './constants';
import { clampToLatBounds } from './elasticsearch_util';
import { MapExtent } from './descriptor_types';

const ZOOM_TILE_KEY_INDEX = 0;
const X_TILE_KEY_INDEX = 1;
const Y_TILE_KEY_INDEX = 2;

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

export function parseTileKey(tileKey) {
export interface ESBounds {
thomasneirynck marked this conversation as resolved.
Show resolved Hide resolved
top_left: {
lon: number;
lat: number;
};
bottom_right: {
lon: number;
lat: number;
};
}

export function parseTileKey(
tileKey: string
): { x: number; y: number; zoom: number; tileCount: number } {
const tileKeyParts = tileKey.split('/');

if (tileKeyParts.length !== 3) {
Expand All @@ -42,7 +56,7 @@ export function parseTileKey(tileKey) {
return { x, y, zoom, tileCount };
}

function sinh(x) {
function sinh(x: number): number {
return (Math.exp(x) - Math.exp(-x)) / 2;
}

Expand All @@ -55,24 +69,52 @@ function sinh(x) {
// We add one extra decimal level of precision because, at high zoom
// levels rounding exactly can cause the boxes to render as uneven sizes
// (some will be slightly larger and some slightly smaller)
function precisionRounding(v, minPrecision, binSize) {
function precisionRounding(v: number, minPrecision: number, binSize: number): number {
let precision = Math.ceil(Math.abs(Math.log10(binSize))) + 1;
precision = Math.max(precision, minPrecision);
return _.round(v, precision);
}

function tileToLatitude(y, tileCount) {
export function tile2long(x: number, z: number): number {
const tileCount = getTileCount(z);
return tileToLongitude(x, tileCount);
}

export function tile2lat(y: number, z: number): number {
const tileCount = getTileCount(z);
return tileToLatitude(y, tileCount);
}

export function tileToESBbox(x: number, y: number, z: number): ESBounds {
const wLon = tile2long(x, z);
const sLat = tile2lat(y + 1, z);
const eLon = tile2long(x + 1, z);
const nLat = tile2lat(y, z);

return {
top_left: {
lon: wLon,
lat: nLat,
},
bottom_right: {
lon: eLon,
lat: sLat,
},
};
}

export function tileToLatitude(y: number, tileCount: number) {
const radians = Math.atan(sinh(Math.PI - (2 * Math.PI * y) / tileCount));
const lat = (180 / Math.PI) * radians;
return precisionRounding(lat, DECIMAL_DEGREES_PRECISION, 180 / tileCount);
}

function tileToLongitude(x, tileCount) {
export function tileToLongitude(x: number, tileCount: number) {
const lon = (x / tileCount) * 360 - 180;
return precisionRounding(lon, DECIMAL_DEGREES_PRECISION, 360 / tileCount);
}

export function getTileBoundingBox(tileKey) {
export function getTileBoundingBox(tileKey: string) {
const { x, y, tileCount } = parseTileKey(tileKey);

return {
Expand All @@ -83,22 +125,22 @@ export function getTileBoundingBox(tileKey) {
};
}

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

function latitudeToTile(lat, tileCount) {
function latitudeToTile(lat: number, tileCount: number) {
const radians = (clampToLatBounds(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) {
function longitudeToTile(lon: number, tileCount: number) {
const x = ((lon + 180) / 360) * tileCount;
return Math.floor(x);
}

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

const upperLeftX = longitudeToTile(extent.minLon, tileCount);
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/maps/public/actions/data_request_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { ILayer } from '../classes/layers/layer';
import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer';
import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types';
import { DataRequestAbortError } from '../classes/util/data_request';
import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_geo_utils';
import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util';
import { IVectorStyle } from '../classes/styles/vector/vector_style';

const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1;
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/maps/public/actions/map_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {
MapRefreshConfig,
} from '../../common/descriptor_types';
import { INITIAL_LOCATION } from '../../common/constants';
import { scaleBounds } from '../../common/elasticsearch_geo_utils';
import { scaleBounds } from '../../common/elasticsearch_util';

export function setMapInitError(errorMessage: string) {
return {
Expand Down
16 changes: 11 additions & 5 deletions x-pack/plugins/maps/public/classes/fields/es_agg_field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { IVectorSource } from '../sources/vector_source';
import { ESDocField } from './es_doc_field';
import { AGG_TYPE, FIELD_ORIGIN } from '../../../common/constants';
import { isMetricCountable } from '../util/is_metric_countable';
import { getField, addFieldToDSL } from '../util/es_agg_utils';
import { getField, addFieldToDSL } from '../../../common/elasticsearch_util';
import { TopTermPercentageField } from './top_term_percentage_field';
import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property';
import { ESAggTooltipProperty } from '../tooltips/es_agg_tooltip_property';
Expand All @@ -30,25 +30,29 @@ export class ESAggField implements IESAggField {
private readonly _label?: string;
private readonly _aggType: AGG_TYPE;
private readonly _esDocField?: IField | undefined;
private readonly _canReadFromGeoJson: boolean;

constructor({
label,
source,
aggType,
esDocField,
origin,
canReadFromGeoJson = true,
}: {
label?: string;
source: IESAggSource;
aggType: AGG_TYPE;
esDocField?: IField;
origin: FIELD_ORIGIN;
canReadFromGeoJson?: boolean;
}) {
this._source = source;
this._origin = origin;
this._label = label;
this._aggType = aggType;
this._esDocField = esDocField;
this._canReadFromGeoJson = canReadFromGeoJson;
}

getSource(): IVectorSource {
Expand Down Expand Up @@ -132,18 +136,19 @@ export class ESAggField implements IESAggField {
}

supportsAutoDomain(): boolean {
return true;
return this._canReadFromGeoJson ? true : this.supportsFieldMeta();
}

canReadFromGeoJson(): boolean {
return true;
return this._canReadFromGeoJson;
}
}

export function esAggFieldsFactory(
aggDescriptor: AggDescriptor,
source: IESAggSource,
origin: FIELD_ORIGIN
origin: FIELD_ORIGIN,
canReadFromGeoJson: boolean = true
): IESAggField[] {
const aggField = new ESAggField({
label: aggDescriptor.label,
Expand All @@ -153,12 +158,13 @@ export function esAggFieldsFactory(
aggType: aggDescriptor.type,
source,
origin,
canReadFromGeoJson,
});

const aggFields: IESAggField[] = [aggField];

if (aggDescriptor.field && aggDescriptor.type === AGG_TYPE.TERMS) {
aggFields.push(new TopTermPercentageField(aggField));
aggFields.push(new TopTermPercentageField(aggField, canReadFromGeoJson));
}

return aggFields;
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/maps/public/classes/fields/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ export interface IField {
getOrdinalFieldMetaRequest(): Promise<unknown>;
getCategoricalFieldMetaRequest(size: number): Promise<unknown>;

// Determines whether Maps-app can automatically determine the domain of the field-values
// Whether Maps-app can automatically determine the domain of the field-values
// if this is not the case (e.g. for .mvt tiled data),
// then styling properties that require the domain to be known cannot use this property.
supportsAutoDomain(): boolean;

// Determinse wheter Maps-app can automatically deterime the domain of the field-values
// Whether Maps-app can automatically determine the domain of the field-values
// _without_ having to retrieve the data as GeoJson
// e.g. for ES-sources, this would use the extended_stats API
supportsFieldMeta(): boolean;
Expand Down
Loading