diff --git a/x-pack/legacy/plugins/maps/common/constants.js b/x-pack/legacy/plugins/maps/common/constants.js index d7f7e353799d7b..a94f33760e4acd 100644 --- a/x-pack/legacy/plugins/maps/common/constants.js +++ b/x-pack/legacy/plugins/maps/common/constants.js @@ -46,6 +46,13 @@ export const ES_GEO_FIELD_TYPE = { GEO_SHAPE: 'geo_shape' }; +export const ES_SPATIAL_RELATIONS = { + INTERSECTS: 'INTERSECTS', + DISJOINT: 'DISJOINT', + WITHIN: 'WITHIN', + CONTAINS: 'CONTAINS' +}; + export const GEO_JSON_TYPE = { POINT: 'Point', MULTI_POINT: 'MultiPoint', @@ -56,6 +63,10 @@ export const GEO_JSON_TYPE = { GEOMETRY_COLLECTION: 'GeometryCollection', }; +export const POLYGON_COORDINATES_EXTERIOR_INDEX = 0; +export const LON_INDEX = 0; +export const LAT_INDEX = 1; + export const EMPTY_FEATURE_COLLECTION = { type: 'FeatureCollection', features: [] diff --git a/x-pack/legacy/plugins/maps/common/i18n_getters.js b/x-pack/legacy/plugins/maps/common/i18n_getters.js index 0055c899e52c72..80027f0958b6bf 100644 --- a/x-pack/legacy/plugins/maps/common/i18n_getters.js +++ b/x-pack/legacy/plugins/maps/common/i18n_getters.js @@ -6,6 +6,8 @@ import { i18n } from '@kbn/i18n'; +import { ES_SPATIAL_RELATIONS } from './constants'; + export function getAppTitle() { return i18n.translate('xpack.maps.appTitle', { defaultMessage: 'Maps' @@ -24,3 +26,26 @@ export function getUrlLabel() { defaultMessage: 'Url' }); } + +export function getEsSpatialRelationLabel(spatialRelation) { + switch (spatialRelation) { + case ES_SPATIAL_RELATIONS.INTERSECTS: + return i18n.translate('xpack.maps.common.esSpatialRelation.intersectsLabel', { + defaultMessage: 'intersects' + }); + case ES_SPATIAL_RELATIONS.DISJOINT: + return i18n.translate('xpack.maps.common.esSpatialRelation.disjointLabel', { + defaultMessage: 'disjoint' + }); + case ES_SPATIAL_RELATIONS.WITHIN: + return i18n.translate('xpack.maps.common.esSpatialRelation.withinLabel', { + defaultMessage: 'WITHIN' + }); + case ES_SPATIAL_RELATIONS.CONTAINS: + return i18n.translate('xpack.maps.common.esSpatialRelation.containsLabel', { + defaultMessage: 'contains' + }); + default: + return spatialRelation; + } +} diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js index 07d6d189437b0f..a583692101f2d5 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js @@ -16,18 +16,25 @@ import { import { DECIMAL_DEGREES_PRECISION, FEATURE_ID_PROPERTY_NAME, - ZOOM_PRECISION + ZOOM_PRECISION, + LON_INDEX } from '../../../../common/constants'; import mapboxgl from 'mapbox-gl'; import MapboxDraw from '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw-unminified'; import DrawRectangle from 'mapbox-gl-draw-rectangle-mode'; import { FeatureTooltip } from '../feature_tooltip'; import { DRAW_TYPE } from '../../../actions/map_actions'; -import { createShapeFilterWithMeta, createExtentFilterWithMeta } from '../../../elasticsearch_geo_utils'; +import { + createSpatialFilterWithBoundingBox, + createSpatialFilterWithGeometry, + getBoundingBoxGeometry, + roundCoordinates +} from '../../../elasticsearch_geo_utils'; import chrome from 'ui/chrome'; import { spritesheet } from '@elastic/maki'; import sprites1 from '@elastic/maki/dist/sprite@1.png'; import sprites2 from '@elastic/maki/dist/sprite@2.png'; +import { i18n } from '@kbn/i18n'; const isRetina = window.devicePixelRatio === 2; const mbDrawModes = MapboxDraw.modes; @@ -84,40 +91,44 @@ export class MBMapContainer extends React.Component { this.props.setTooltipState(null); }; - _onDraw = async (e) => { - + _onDraw = (e) => { if (!e.features.length) { return; } - const { geoField, geoFieldType, indexPatternId, drawType } = this.props.drawState; - this.props.disableDrawState(); - - - let filter; - if (drawType === DRAW_TYPE.POLYGON) { - filter = createShapeFilterWithMeta(e.features[0].geometry, indexPatternId, geoField, geoFieldType); - } else if (drawType === DRAW_TYPE.BOUNDS) { - const coordinates = e.features[0].geometry.coordinates[0]; - const extent = { - minLon: coordinates[0][0], - minLat: coordinates[0][1], - maxLon: coordinates[0][0], - maxLat: coordinates[0][1] - }; - for (let i = 1; i < coordinates.length; i++) { - extent.minLon = Math.min(coordinates[i][0], extent.minLon); - extent.minLat = Math.min(coordinates[i][1], extent.minLat); - extent.maxLon = Math.max(coordinates[i][0], extent.maxLon); - extent.maxLat = Math.max(coordinates[i][1], extent.maxLat); - } - filter = createExtentFilterWithMeta(extent, indexPatternId, geoField, geoFieldType); - } - if (!filter) { - return; - } + const isBoundingBox = this.props.drawState.drawType === DRAW_TYPE.BOUNDS; + const geometry = e.features[0].geometry; + // MapboxDraw returns coordinates with 12 decimals. Round to a more reasonable number + roundCoordinates(geometry.coordinates); - this.props.addFilters([filter]); + try { + const options = { + indexPatternId: this.props.drawState.indexPatternId, + geoFieldName: this.props.drawState.geoField, + geoFieldType: this.props.drawState.geoFieldType, + }; + const filter = isBoundingBox + ? createSpatialFilterWithBoundingBox({ + ...options, + geometryLabel: i18n.translate('xpack.maps.drawControl.defaultEnvelopeLabel', { + defaultMessage: 'extent' + }), + geometry: getBoundingBoxGeometry(geometry) + }) + : createSpatialFilterWithGeometry({ + ...options, + geometryLabel: i18n.translate('xpack.maps.drawControl.defaultShapeLabel', { + defaultMessage: 'shape' + }), + geometry + }); + this.props.addFilters([filter]); + } catch (error) { + // TODO notify user why filter was not created + console.log(error); + } finally { + this.props.disableDrawState(); + } }; _debouncedSync = _.debounce(() => { @@ -233,8 +244,8 @@ export class MBMapContainer extends React.Component { // Ensure that if the map is zoomed out such that multiple // copies of the feature are visible, the popup appears // over the copy being pointed to. - while (Math.abs(mbLngLat.lng - coordinates[0]) > 180) { - coordinates[0] += mbLngLat.lng > coordinates[0] ? 360 : -360; + while (Math.abs(mbLngLat.lng - coordinates[LON_INDEX]) > 180) { + coordinates[0] += mbLngLat.lng > coordinates[LON_INDEX] ? 360 : -360; } popupAnchorLocation = coordinates; diff --git a/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js b/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js index 084d652c5b47e4..34f7ddf7700fed 100644 --- a/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js +++ b/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.js @@ -8,7 +8,43 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import { parse } from 'wellknown'; import { decodeGeoHash } from 'ui/utils/decode_geo_hash'; -import { DECIMAL_DEGREES_PRECISION, ES_GEO_FIELD_TYPE, GEO_JSON_TYPE } from '../common/constants'; +import { + DECIMAL_DEGREES_PRECISION, + ES_GEO_FIELD_TYPE, + ES_SPATIAL_RELATIONS, + GEO_JSON_TYPE, + POLYGON_COORDINATES_EXTERIOR_INDEX, + LON_INDEX, + LAT_INDEX, +} from '../common/constants'; +import { getEsSpatialRelationLabel } from '../common/i18n_getters'; + +function ensureGeoField(type) { + const expectedTypes = [ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE]; + if (!expectedTypes.includes(type)) { + const errorMessage = i18n.translate('xpack.maps.es_geo_utils.unsupportedFieldTypeErrorMessage', { + defaultMessage: 'Unsupported field type, expected: {expectedTypes}, you provided: {fieldType}', + values: { + fieldType: type, + expectedTypes: expectedTypes.join(',') + } + }); + throw new Error(errorMessage); + } +} + +function ensureGeometryType(type, expectedTypes) { + if (!expectedTypes.includes(type)) { + const errorMessage = i18n.translate('xpack.maps.es_geo_utils.unsupportedGeometryTypeErrorMessage', { + defaultMessage: 'Unsupported geometry type, expected: {expectedTypes}, you provided: {geometryType}', + values: { + geometryType: type, + expectedTypes: expectedTypes.join(',') + } + }); + throw new Error(errorMessage); + } +} /** * Converts Elasticsearch search results into GeoJson FeatureCollection @@ -28,17 +64,14 @@ export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType) { const properties = flattenHit(hits[i]); tmpGeometriesAccumulator.length = 0;//truncate accumulator + + ensureGeoField(geoFieldType); if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { geoPointToGeometry(properties[geoFieldName], tmpGeometriesAccumulator); - } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { - geoShapeToGeometry(properties[geoFieldName], tmpGeometriesAccumulator); } else { - const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.unsupportedFieldTypeErrorMessage', { - defaultMessage: 'Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}', - values: { geoFieldType } - }); - throw new Error(errorMessage); + geoShapeToGeometry(properties[geoFieldName], tmpGeometriesAccumulator); } + // don't include geometry field value in properties delete properties[geoFieldName]; @@ -92,7 +125,7 @@ export function geoPointToGeometry(value, accumulator) { } if (!Array.isArray(value)) { - const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.unsupportedGeoPointValueErrorMessage', { + const errorMessage = i18n.translate('xpack.maps.es_geo_utils.unsupportedGeoPointValueErrorMessage', { defaultMessage: `Unsupported geo_point value: {geoPointValue}`, values: { geoPointValue: value @@ -104,8 +137,8 @@ export function geoPointToGeometry(value, accumulator) { if (value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number') { - const lat = value[1]; - const lon = value[0]; + const lat = value[LAT_INDEX]; + const lon = value[LON_INDEX]; accumulator.push(pointGeometryFactory(lat, lon)); return; } @@ -153,7 +186,7 @@ export function convertESShapeToGeojsonGeometry(value) { break; case 'envelope': case 'circle': - const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.convert.unsupportedGeometryTypeErrorMessage', { + const errorMessage = i18n.translate('xpack.maps.es_geo_utils.convert.unsupportedGeometryTypeErrorMessage', { defaultMessage: `Unable to convert {geometryType} geometry to geojson, not supported`, values: { geometryType: geoJson.type @@ -168,7 +201,7 @@ function convertWKTStringToGeojson(value) { try { return parse(value); } catch (e) { - const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.wkt.invalidWKTErrorMessage', { + const errorMessage = i18n.translate('xpack.maps.es_geo_utils.wkt.invalidWKTErrorMessage', { defaultMessage: `Unable to convert {wkt} to geojson. Valid WKT expected.`, values: { wkt: value @@ -178,7 +211,6 @@ function convertWKTStringToGeojson(value) { } } - export function geoShapeToGeometry(value, accumulator) { if (!value) { @@ -203,118 +235,143 @@ export function geoShapeToGeometry(value, accumulator) { accumulator.push(geoJson); } -const POLYGON_COORDINATES_EXTERIOR_INDEX = 0; -const TOP_LEFT_INDEX = 0; -const BOTTOM_RIGHT_INDEX = 2; +function createGeoBoundBoxFilter(geometry, geoFieldName, filterProps = {}) { + ensureGeometryType(geometry.type, [GEO_JSON_TYPE.POLYGON]); + + const TOP_LEFT_INDEX = 0; + const BOTTOM_RIGHT_INDEX = 2; + const verticies = geometry.coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX]; + return { + geo_bounding_box: { + [geoFieldName]: { + top_left: verticies[TOP_LEFT_INDEX], + bottom_right: verticies[BOTTOM_RIGHT_INDEX] + } + }, + ...filterProps + }; +} export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { + ensureGeoField(geoFieldType); + const safePolygon = convertMapExtentToPolygon(mapExtent); + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { - const verticies = safePolygon.coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX]; - return { - geo_bounding_box: { - [geoFieldName]: { - top_left: verticies[TOP_LEFT_INDEX], - bottom_right: verticies[BOTTOM_RIGHT_INDEX] - } + return createGeoBoundBoxFilter(safePolygon, geoFieldName); + } + + return { + geo_shape: { + [geoFieldName]: { + shape: safePolygon, + relation: ES_SPATIAL_RELATIONS.INTERSECTS } - }; - } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { + } + }; +} + +export function createSpatialFilterWithBoundingBox(options) { + return createGeometryFilterWithMeta({ ...options, isBoundingBox: true }); +} + +export function createSpatialFilterWithGeometry(options) { + return createGeometryFilterWithMeta(options); +} + +function createGeometryFilterWithMeta({ + geometry, + geometryLabel, + indexPatternId, + geoFieldName, + geoFieldType, + relation = ES_SPATIAL_RELATIONS.INTERSECTS, + isBoundingBox = false, +}) { + + ensureGeoField(geoFieldType); + + const relationLabel = geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT + ? i18n.translate('xpack.maps.es_geo_utils.shapeFilter.geoPointRelationLabel', { + defaultMessage: 'in' + }) + : getEsSpatialRelationLabel(relation); + const meta = { + negate: false, + index: indexPatternId, + alias: `${geoFieldName} ${relationLabel} ${geometryLabel}` + }; + + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { return { + meta, geo_shape: { + ignore_unmapped: true, [geoFieldName]: { - shape: safePolygon, - relation: 'INTERSECTS' + shape: geometry, + relation } } }; - } else { - const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.extent.unsupportedGeoFieldTypeErrorMessage', { - defaultMessage: `Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}`, - values: { geoFieldType } - }); - throw new Error(errorMessage); } -} + // geo_points supports limited geometry types + // TODO add support for multi_polygon + ensureGeometryType(geometry.type, [GEO_JSON_TYPE.POLYGON]); -export function createExtentFilterWithMeta(mapExtent, indexPatternId, geoFieldName, geoFieldType) { - - const roundedExtent = { - minLon: _.round(mapExtent.minLon, DECIMAL_DEGREES_PRECISION), - minLat: _.round(mapExtent.minLat, DECIMAL_DEGREES_PRECISION), - maxLon: _.round(mapExtent.maxLon, DECIMAL_DEGREES_PRECISION), - maxLat: _.round(mapExtent.maxLat, DECIMAL_DEGREES_PRECISION) - }; + if (isBoundingBox) { + return createGeoBoundBoxFilter(geometry, geoFieldName, { meta }); + } - const filter = createExtentFilter(roundedExtent, geoFieldName, geoFieldType); - filter.meta = { - negate: false, - index: indexPatternId, - alias: i18n.translate('xpack.maps.elasticsearch_geo_utils.extentFilter.aliasTitle', { - defaultMessage: `extent at {coordinate}`, - values: { - coordinate: `[${roundedExtent.minLon}, ${roundedExtent.minLat}, ${roundedExtent.maxLon}, ${roundedExtent.maxLat}]` + return { + meta, + geo_polygon: { + ignore_unmapped: true, + [geoFieldName]: { + points: geometry.coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX].map(coordinatePair => { + return { + lon: coordinatePair[LON_INDEX], + lat: coordinatePair[LAT_INDEX] + }; + }) } - }) + } }; - return filter; } -export function createShapeFilterWithMeta(geojsonPolygon, indexPatternId, geoFieldName, geoFieldType) { - - const filter = { - meta: { - negate: false, - index: indexPatternId, - alias: i18n.translate('xpack.maps.elasticsearch_geo_utils.shapeFilter.aliasTitle', { - defaultMessage: `shape at {coordinate}`, - values: { - // eslint-disable-next-line max-len - coordinate: `${_.round(geojsonPolygon.coordinates[0][0][0], DECIMAL_DEGREES_PRECISION)}, ${_.round(geojsonPolygon.coordinates[0][0][1], DECIMAL_DEGREES_PRECISION)}` - } - }) +export function roundCoordinates(coordinates) { + for (let i = 0; i < coordinates.length; i++) { + const value = coordinates[i]; + if (Array.isArray(value)) { + roundCoordinates(value); + } else if (!isNaN(value)) { + coordinates[i] = _.round(value, DECIMAL_DEGREES_PRECISION); } - }; - - if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { - const pointsArray = geojsonPolygon.coordinates[0].map(coordinatePair => { - return { - lon: _.round(coordinatePair[0], DECIMAL_DEGREES_PRECISION), - lat: _.round(coordinatePair[1], DECIMAL_DEGREES_PRECISION) - }; - }); - filter.geo_polygon = { - ignore_unmapped: true, - [geoFieldName]: { - points: pointsArray - } - }; - } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { - const geojsonCoordinateArray = geojsonPolygon.coordinates[0].map(coordinatePair => { - return [_.round(coordinatePair[0], DECIMAL_DEGREES_PRECISION), _.round(coordinatePair[1], DECIMAL_DEGREES_PRECISION)]; - }); - filter.geo_shape = { - ignore_unmapped: true, - [geoFieldName]: { - shape: { - type: 'Polygon', - coordinates: [geojsonCoordinateArray] - }, - relation: 'INTERSECTS' - } - }; - } else { - const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.shape.unsupportedGeoFieldTypeErrorMessage', { - defaultMessage: `Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}`, - values: { geoFieldType } - }); - throw new Error(errorMessage); } - return filter; } +/* + * returns Polygon geometry where coordinates define a bounding box that contains the input geometry + */ +export function getBoundingBoxGeometry(geometry) { + ensureGeometryType(geometry.type, [GEO_JSON_TYPE.POLYGON]); + + const exterior = geometry.coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX]; + const extent = { + minLon: exterior[0][LON_INDEX], + minLat: exterior[0][LAT_INDEX], + maxLon: exterior[0][LON_INDEX], + maxLat: exterior[0][LAT_INDEX] + }; + for (let i = 1; i < exterior.length; i++) { + extent.minLon = Math.min(exterior[i][LON_INDEX], extent.minLon); + extent.minLat = Math.min(exterior[i][LAT_INDEX], extent.minLat); + extent.maxLon = Math.max(exterior[i][LON_INDEX], extent.maxLon); + extent.maxLat = Math.max(exterior[i][LAT_INDEX], extent.maxLat); + } + return convertMapExtentToPolygon(extent); +} function formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }) { // GeoJSON mandates that the outer polygon must be counterclockwise to avoid ambiguous polygons @@ -328,7 +385,7 @@ function formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }) { const bottomRight = [right, bottom]; const topRight = [right, top]; return { - 'type': 'polygon', + 'type': GEO_JSON_TYPE.POLYGON, 'coordinates': [ [ topLeft, bottomLeft, bottomRight, topRight, topLeft ] ] diff --git a/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.test.js b/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.test.js index dfffcb65279f49..14973a1e86297b 100644 --- a/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.test.js +++ b/x-pack/legacy/plugins/maps/public/elasticsearch_geo_utils.test.js @@ -12,6 +12,7 @@ import { geoShapeToGeometry, createExtentFilter, convertMapExtentToPolygon, + roundCoordinates, } from './elasticsearch_geo_utils'; import { flattenHitWrapper } from 'ui/index_patterns'; @@ -332,7 +333,7 @@ describe('createExtentFilter', () => { 'coordinates': [ [[-89, 39], [-89, 35], [-83, 35], [-83, 39], [-89, 39]] ], - 'type': 'polygon' + 'type': 'Polygon' } } } @@ -355,7 +356,7 @@ describe('createExtentFilter', () => { 'coordinates': [ [[-180, 39], [-180, 35], [180, 35], [180, 39], [-180, 39]] ], - 'type': 'polygon' + 'type': 'Polygon' } } } @@ -372,7 +373,7 @@ describe('convertMapExtentToPolygon', () => { minLon: 90, }; expect(convertMapExtentToPolygon(bounds)).toEqual({ - 'type': 'polygon', + 'type': 'Polygon', 'coordinates': [ [[90, 10], [90, -10], [100, -10], [100, 10], [90, 10]] ] @@ -387,7 +388,7 @@ describe('convertMapExtentToPolygon', () => { minLon: -400, }; expect(convertMapExtentToPolygon(bounds)).toEqual({ - 'type': 'polygon', + 'type': 'Polygon', 'coordinates': [ [[-180, 10], [-180, -10], [180, -10], [180, 10], [-180, 10]] ] @@ -402,7 +403,7 @@ describe('convertMapExtentToPolygon', () => { minLon: -400, }; expect(convertMapExtentToPolygon(bounds)).toEqual({ - 'type': 'polygon', + 'type': 'Polygon', 'coordinates': [ [[-180, 10], [-180, -10], [180, -10], [180, 10], [-180, 10]] ] @@ -417,7 +418,7 @@ describe('convertMapExtentToPolygon', () => { minLon: 170, }; expect(convertMapExtentToPolygon(bounds)).toEqual({ - 'type': 'polygon', + 'type': 'Polygon', 'coordinates': [ [[170, 10], [170, -10], [-170, -10], [-170, 10], [170, 10]] ] @@ -432,10 +433,26 @@ describe('convertMapExtentToPolygon', () => { minLon: -190, }; expect(convertMapExtentToPolygon(bounds)).toEqual({ - 'type': 'polygon', + 'type': 'Polygon', 'coordinates': [ [[170, 10], [170, -10], [-170, -10], [-170, 10], [170, 10]] ] }); }); }); + +describe('roundCoordinates', () => { + it('should set coordinates precision', () => { + const coordinates = [ + [110.21515290475513, 40.23193047044205], + [-105.30620093073654, 40.23193047044205], + [-105.30620093073654, 30.647128842617803] + ]; + roundCoordinates(coordinates); + expect(coordinates).toEqual([ + [110.21515, 40.23193], + [-105.30620, 40.23193], + [-105.3062, 30.64713] + ]); + }); +}); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 46592b31d0bb2c..a7310b1fed816d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -5452,14 +5452,6 @@ "xpack.maps.appTitle": "Maps", "xpack.maps.badge.readOnly.text": "読み込み専用", "xpack.maps.badge.readOnly.tooltip": "マップを保存できませんで", - "xpack.maps.elasticsearch_geo_utils.convert.unsupportedGeometryTypeErrorMessage": "{geometryType} ジオメトリから Geojson に変換できません。サポートされていません", - "xpack.maps.elasticsearch_geo_utils.extent.unsupportedGeoFieldTypeErrorMessage": "サポートされていないフィールドタイプ、期待値: geo_shape または geo_point、入力値: {geoFieldType}", - "xpack.maps.elasticsearch_geo_utils.extentFilter.aliasTitle": "{coordinate}で拡張", - "xpack.maps.elasticsearch_geo_utils.shape.unsupportedGeoFieldTypeErrorMessage": "サポートされていないフィールドタイプ、期待値: geo_shape または geo_point、入力値: {geoFieldType}", - "xpack.maps.elasticsearch_geo_utils.shapeFilter.aliasTitle": "{coordinate} で形成", - "xpack.maps.elasticsearch_geo_utils.unsupportedFieldTypeErrorMessage": "サポートされていないフィールドタイプ、期待値: geo_shape または geo_point、入力値: {geoFieldType}", - "xpack.maps.elasticsearch_geo_utils.unsupportedGeoPointValueErrorMessage": "サポートされていない geo_point 値: {geoPointValue}", - "xpack.maps.elasticsearch_geo_utils.wkt.invalidWKTErrorMessage": "{wkt} を Geojson に変換できません。有効な WKT が必要です。", "xpack.maps.esSearch.featureCountMsg": "{count} 件のドキュメントが見つかりました。", "xpack.maps.esSearch.resultsTrimmedMsg": "結果は初めの {count} 件のドキュメントに制限されています。", "xpack.maps.esSearch.topHitsEntitiesCountMsg": "{entityCount} 件のエントリーを発見.", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d2da40778bbbdd..94bd51e7e529fa 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -5595,14 +5595,6 @@ "xpack.maps.appTitle": "Maps", "xpack.maps.badge.readOnly.text": "只读", "xpack.maps.badge.readOnly.tooltip": "无法保存地图", - "xpack.maps.elasticsearch_geo_utils.convert.unsupportedGeometryTypeErrorMessage": "无法将 {geometryType} 几何图形转换成 geojson,不支持", - "xpack.maps.elasticsearch_geo_utils.extent.unsupportedGeoFieldTypeErrorMessage": "字段类型不受支持,应为:geo_shape 或 geo_point,而您提供的是:{geoFieldType}", - "xpack.maps.elasticsearch_geo_utils.extentFilter.aliasTitle": "位于 {coordinate} 的范围", - "xpack.maps.elasticsearch_geo_utils.shape.unsupportedGeoFieldTypeErrorMessage": "字段类型不受支持,应为:geo_shape 或 geo_point,而您提供的是:{geoFieldType}", - "xpack.maps.elasticsearch_geo_utils.shapeFilter.aliasTitle": "位于 {coordinate} 的形状", - "xpack.maps.elasticsearch_geo_utils.unsupportedFieldTypeErrorMessage": "字段类型不受支持,应为:geo_shape 或 geo_point,而您提供的是:{geoFieldType}", - "xpack.maps.elasticsearch_geo_utils.unsupportedGeoPointValueErrorMessage": "不受支持的 geo_point 值:{geoPointValue}", - "xpack.maps.elasticsearch_geo_utils.wkt.invalidWKTErrorMessage": "无法将 {wkt} 转换成 geojson。需要有效的 WKT。", "xpack.maps.esSearch.featureCountMsg": "找到 {count} 个文档。", "xpack.maps.esSearch.resultsTrimmedMsg": "结果仅限于前 {count} 个文档。", "xpack.maps.esSearch.topHitsEntitiesCountMsg": "找到 {entityCount} 个实体。",