Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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: 8 additions & 0 deletions src/core_plugins/kbn_vislib_vis_types/public/tile_map.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ export default function TileMapVisType(Private, getAppState, courier, config) {
{ schema: 'metric', type: 'count' }
]
},
{
group: 'metrics',
name: 'centroid',
title: 'Geo Centroid',
aggFilter: 'geo_centroid',
min: 0,
max: 1
},
{
group: 'buckets',
name: 'segment',
Expand Down
11 changes: 10 additions & 1 deletion src/fixtures/agg_resp/geohash_grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export default function GeoHashGridAggResponseFixture() {
// aggs:[
// { schema: 'metric', type: 'avg', params: { field: 'bytes' } },
// { schema: 'split', type: 'terms', params: { field: '@tags', size: 10 } },
// { schema: 'segment', type: 'geohash_grid', params: { field: 'geo.coordinates', precision: 3 } }
// { schema: 'segment', type: 'geohash_grid', params: { field: 'geo.coordinates', precision: 3 } },
// { schema: 'centroid', type: 'geo_centroid', params: { field: 'geo.coordinates' } }
// ],
// params: {
// isDesaturated: true,
Expand All @@ -34,6 +35,8 @@ export default function GeoHashGridAggResponseFixture() {
.sort()
.map(function (geoHash) {
const count = _.random(1, 5000);
const lat = _.random(-180, 180, true);
const lon = _.random(-180, 180, true);

totalDocCount += count;
docCount += count;
Expand All @@ -43,6 +46,12 @@ export default function GeoHashGridAggResponseFixture() {
doc_count: count,
1: {
value: 2048 + i
},
4: {
location: {
lat: lat,
lon: lon
}
}
};
});
Expand Down
15 changes: 11 additions & 4 deletions src/ui/public/agg_response/geo_json/__tests__/geo_json.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ describe('GeoJson Agg Response Converter', function () {
aggs: [
{ schema: 'metric', type: 'avg', params: { field: 'bytes' } },
{ schema: 'split', type: 'terms', params: { field: '@tags' } },
{ schema: 'segment', type: 'geohash_grid', params: { field: 'geo.coordinates', precision: 3 } }
{ schema: 'segment', type: 'geohash_grid', params: { field: 'geo.coordinates', precision: 3 } },
{ schema: 'centroid', type: 'geo_centroid', params: { field: 'geo.coordinates' } }
],
params: {
isDesaturated: true,
Expand All @@ -40,7 +41,8 @@ describe('GeoJson Agg Response Converter', function () {
aggs = {
metric: vis.aggs[0],
split: vis.aggs[1],
geo: vis.aggs[2]
geo: vis.aggs[2],
centroid: vis.aggs[3]
};
}));

Expand Down Expand Up @@ -112,12 +114,14 @@ describe('GeoJson Agg Response Converter', function () {
let chart;
let geoColI;
let metricColI;
let centroidColI;

before(function () {
table = makeTable();
chart = makeSingleChart(table);
geoColI = _.findIndex(table.columns, { aggConfig: aggs.geo });
metricColI = _.findIndex(table.columns, { aggConfig: aggs.metric });
centroidColI = _.findIndex(table.columns, { aggConfig: aggs.centroid });
});

it('should be geoJson format', function () {
Expand Down Expand Up @@ -145,10 +149,11 @@ describe('GeoJson Agg Response Converter', function () {
it('should have value properties data', function () {
table.rows.forEach(function (row, i) {
const props = chart.geoJson.features[i].properties;
const keys = ['value', 'geohash', 'aggConfigResult', 'rectangle', 'center'];
const keys = ['value', 'geohash', 'aggConfigResult', 'rectangle', 'center', 'centroid'];
expect(props).to.be.an('object');
expect(props).to.only.have.keys(keys);
expect(props.geohash).to.be.a('string');
expect(props.centroid).to.be.an('object');
if (props.value != null) expect(props.value).to.be.a('number');
});
});
Expand All @@ -157,7 +162,7 @@ describe('GeoJson Agg Response Converter', function () {
table.rows.forEach(function (row, i) {
const geometry = chart.geoJson.features[i].geometry;
const props = chart.geoJson.features[i].properties;
expect(props.center).to.eql(geometry.coordinates.slice(0).reverse());
expect(props.centroid).to.eql({ lat: geometry.coordinates[1], lon: geometry.coordinates[0] });
});
});

Expand All @@ -168,10 +173,12 @@ describe('GeoJson Agg Response Converter', function () {
expect(props.aggConfigResult).to.be(row[metricColI]);
expect(props.value).to.be(row[metricColI].value);
expect(props.geohash).to.be(row[geoColI].value);
expect(props.centroid).to.be(row[centroidColI].value);
} else {
expect(props.aggConfigResult).to.be(null);
expect(props.value).to.be(row[metricColI]);
expect(props.geohash).to.be(row[geoColI]);
expect(props.centroid).to.be(row[centroidColI]);
}
});
});
Expand Down
3 changes: 2 additions & 1 deletion src/ui/public/agg_response/geo_json/geo_json.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ export default function TileMapConverterFn(Private, timefilter, $compile, $rootS

const geoI = columnIndex('segment');
const metricI = columnIndex('metric');
const centroidI = columnIndex('centroid');
const geoAgg = _.get(table.columns, [geoI, 'aggConfig']);
const metricAgg = _.get(table.columns, [metricI, 'aggConfig']);

const features = rowsToFeatures(table, geoI, metricI);
const features = rowsToFeatures(table, geoI, metricI, centroidI);
const values = features.map(function (feature) {
return feature.properties.value;
});
Expand Down
17 changes: 14 additions & 3 deletions src/ui/public/agg_response/geo_json/rows_to_features.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function unwrap(val) {
return getAcr(val) ? val.value : val;
}

function convertRowsToFeatures(table, geoI, metricI) {
function convertRowsToFeatures(table, geoI, metricI, centroidI) {
return _.transform(table.rows, function (features, row) {
const geohash = unwrap(row[geoI]);
if (!geohash) return;
Expand All @@ -23,6 +23,16 @@ function convertRowsToFeatures(table, geoI, metricI) {
location.longitude[2]
];

// fetch geo centroid and use it as point of feature if it exists
let point = centerLatLng;
const centroid = unwrap(row[centroidI]);
if (centroid) {
point = [
centroid.lat,
centroid.lon
];
}

// order is nw, ne, se, sw
const rectangle = [
[location.latitude[0], location.longitude[0]],
Expand All @@ -37,14 +47,15 @@ function convertRowsToFeatures(table, geoI, metricI) {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: centerLatLng.slice(0).reverse()
coordinates: point.slice(0).reverse()
},
properties: {
geohash: geohash,
value: unwrap(row[metricI]),
aggConfigResult: getAcr(row[metricI]),
center: centerLatLng,
rectangle: rectangle
rectangle: rectangle,
centroid: centroid
}
});
}, []);
Expand Down
4 changes: 3 additions & 1 deletion src/ui/public/agg_types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import AggTypesMetricsStdDeviationProvider from 'ui/agg_types/metrics/std_deviat
import AggTypesMetricsCardinalityProvider from 'ui/agg_types/metrics/cardinality';
import AggTypesMetricsPercentilesProvider from 'ui/agg_types/metrics/percentiles';
import AggTypesMetricsPercentileRanksProvider from 'ui/agg_types/metrics/percentile_ranks';
import AggTypesMetricsGeoCentroidProvider from 'ui/agg_types/metrics/geo_centroid';
import AggTypesBucketsDateHistogramProvider from 'ui/agg_types/buckets/date_histogram';
import AggTypesBucketsHistogramProvider from 'ui/agg_types/buckets/histogram';
import AggTypesBucketsRangeProvider from 'ui/agg_types/buckets/range';
Expand All @@ -34,7 +35,8 @@ export default function AggTypeService(Private) {
Private(AggTypesMetricsCardinalityProvider),
Private(AggTypesMetricsPercentilesProvider),
Private(AggTypesMetricsPercentileRanksProvider),
Private(AggTypesMetricsTopHitProvider)
Private(AggTypesMetricsTopHitProvider),
Private(AggTypesMetricsGeoCentroidProvider)
],
buckets: [
Private(AggTypesBucketsDateHistogramProvider),
Expand Down
23 changes: 23 additions & 0 deletions src/ui/public/agg_types/metrics/geo_centroid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import AggTypesMetricsMetricAggTypeProvider from 'ui/agg_types/metrics/metric_agg_type';

export default function AggTypeMetricGeoCentroidProvider(Private) {
const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider);

return new MetricAggType({
name: 'geo_centroid',
title: 'Geo Centroid',
makeLabel: function (aggConfig) {
return 'Geo Centroid';
},
params: [
{
name: 'field',
filterFieldTypes: 'geo_point'
}
],
getValue: function (agg, bucket) {
return bucket[agg.id] && bucket[agg.id].location;
}
});
}

6 changes: 4 additions & 2 deletions src/ui/public/vis_maps/__tests__/tile_maps/markers.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ describe('tilemaptest - Marker Tests', function () {
const index = _.random(mapData.features.length - 1);
const feature = mapData.features[index];
const featureValue = feature.properties.value;
const featureArr = feature.geometry.coordinates.slice(0).concat(featureValue);
// Reverse coordinates since _dataToHeatArray returns LatLng and geoJson coordinates are in LngLat
const featureArr = feature.geometry.coordinates.slice(0).reverse().concat(featureValue);
expect(arr[index]).to.eql(featureArr);
});
});
Expand All @@ -306,7 +307,8 @@ describe('tilemaptest - Marker Tests', function () {
const index = _.random(mapData.features.length - 1);
const feature = mapData.features[index];
const featureValue = feature.properties.value / max;
const featureArr = feature.geometry.coordinates.slice(0).concat(featureValue);
// Reverse coordinates since _dataToHeatArray returns LatLng and geoJson coordinates are in LngLat
const featureArr = feature.geometry.coordinates.slice(0).reverse().concat(featureValue);
expect(arr[index]).to.eql(featureArr);
});
});
Expand Down
4 changes: 2 additions & 2 deletions src/ui/public/vis_maps/visualizations/marker_types/heatmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ export default function HeatmapMarkerFactory(Private) {
const self = this;

return this.geoJson.features.map(function (feature) {
const lat = feature.properties.center[0];
const lng = feature.properties.center[1];
const lat = feature.geometry.coordinates[1];
const lng = feature.geometry.coordinates[0];
let heatIntensity;

if (!self._attr.heatNormalizeData) {
Expand Down